]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
x86 bridgeboard: DOSBox x86 CPU core and mainboard support chip emulation.
authorToni Wilen <twilen@winuae.net>
Mon, 27 Jul 2015 16:24:15 +0000 (19:24 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 27 Jul 2015 16:24:15 +0000 (19:24 +0300)
45 files changed:
dosbox/callback.h [new file with mode: 0644]
dosbox/cmos.cpp [new file with mode: 0644]
dosbox/core_full.cpp [new file with mode: 0644]
dosbox/core_full/ea_lookup.h [new file with mode: 0644]
dosbox/core_full/load.h [new file with mode: 0644]
dosbox/core_full/loadwrite.h [new file with mode: 0644]
dosbox/core_full/op.h [new file with mode: 0644]
dosbox/core_full/optable.h [new file with mode: 0644]
dosbox/core_full/save.h [new file with mode: 0644]
dosbox/core_full/string.h [new file with mode: 0644]
dosbox/core_full/support.h [new file with mode: 0644]
dosbox/core_normal.cpp [new file with mode: 0644]
dosbox/core_normal/helpers.h [new file with mode: 0644]
dosbox/core_normal/prefix_0f.h [new file with mode: 0644]
dosbox/core_normal/prefix_66.h [new file with mode: 0644]
dosbox/core_normal/prefix_66_0f.h [new file with mode: 0644]
dosbox/core_normal/prefix_none.h [new file with mode: 0644]
dosbox/core_normal/string.h [new file with mode: 0644]
dosbox/core_normal/support.h [new file with mode: 0644]
dosbox/core_normal/table_ea.h [new file with mode: 0644]
dosbox/core_simple.cpp [new file with mode: 0644]
dosbox/cpu.cpp [new file with mode: 0644]
dosbox/cpu.h [new file with mode: 0644]
dosbox/db_memory.cpp [new file with mode: 0644]
dosbox/dosbox.h [new file with mode: 0644]
dosbox/flags.cpp [new file with mode: 0644]
dosbox/fpu.cpp [new file with mode: 0644]
dosbox/fpu.h [new file with mode: 0644]
dosbox/fpu_instructions.h [new file with mode: 0644]
dosbox/fpu_instructions_x86.h [new file with mode: 0644]
dosbox/inout.h [new file with mode: 0644]
dosbox/instructions.h [new file with mode: 0644]
dosbox/keyboard.cpp [new file with mode: 0644]
dosbox/lazyflags.h [new file with mode: 0644]
dosbox/logging.h [new file with mode: 0644]
dosbox/mem.h [new file with mode: 0644]
dosbox/modrm.cpp [new file with mode: 0644]
dosbox/modrm.h [new file with mode: 0644]
dosbox/paging.cpp [new file with mode: 0644]
dosbox/paging.h [new file with mode: 0644]
dosbox/pic.cpp [new file with mode: 0644]
dosbox/pic.h [new file with mode: 0644]
dosbox/regs.h [new file with mode: 0644]
dosbox/setup.h [new file with mode: 0644]
dosbox/support.h [new file with mode: 0644]

diff --git a/dosbox/callback.h b/dosbox/callback.h
new file mode 100644 (file)
index 0000000..c4e6fa6
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  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: callback.h,v 1.26 2009-08-23 17:24:54 c2woody Exp $ */
+
+#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 };
+
+#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);
+
+       //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/dosbox/cmos.cpp b/dosbox/cmos.cpp
new file mode 100644 (file)
index 0000000..bf3d67e
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ *  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: cmos.cpp,v 1.29 2009-06-16 18:19:18 qbix79 Exp $ */
+
+#include <time.h>
+#include <math.h>
+
+#include "dosbox.h"
+//#include "timer.h"
+#include "pic.h"
+#include "inout.h"
+#include "mem.h"
+//#include "bios_disk.h"
+#include "setup.h"
+//#include "cross.h" //fmod on certain platforms
+
+static struct {
+       Bit8u regs[0x40];
+       bool nmi;
+       bool bcd;
+       Bit8u reg;
+       struct {
+               bool enabled;
+               Bit8u div;
+               float delay;
+               bool acknowledged;
+       } timer;
+       struct {
+               double timer;
+               double ended;
+               double alarm;
+       } last;
+       bool update_ended;
+} cmos;
+
+Bit8u *x86_cmos_regs(Bit8u *regs)
+{
+       if (regs) {
+               memcpy(cmos.regs, regs, 0x40);
+       }
+       return cmos.regs;
+}
+
+static void cmos_timerevent(Bitu val) {
+       if (cmos.timer.acknowledged) {
+               cmos.timer.acknowledged=false;
+               PIC_ActivateIRQ(8);
+       }
+       if (cmos.timer.enabled) {
+//             PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
+               cmos.regs[0xc] = 0xC0;//Contraption Zack (music)
+       }
+}
+
+static void cmos_checktimer(void) {
+       //PIC_RemoveEvents(cmos_timerevent);    
+       if (cmos.timer.div<=2) cmos.timer.div+=7;
+       cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1))));
+       if (!cmos.timer.div || !cmos.timer.enabled) return;
+       LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay);
+//     PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
+       /* A rtc is always running */
+       double remd=fmod(PIC_FullIndex(),(double)cmos.timer.delay);
+       //PIC_AddEvent(cmos_timerevent,(float)((double)cmos.timer.delay-remd)); //Should be more like a real pc. Check
+//     status reg A reading with this (and with other delays actually)
+}
+
+void cmos_selreg(Bitu port,Bitu val,Bitu iolen) {
+       cmos.reg=val & 0x3f;
+       cmos.nmi=(val & 0x80)>0;
+}
+
+void cmos_writereg(Bitu port,Bitu val,Bitu iolen)
+{
+       switch (cmos.reg)
+       {
+       case 0x00:              /* Seconds */
+       case 0x02:              /* Minutes */
+       case 0x04:              /* Hours */
+       case 0x06:              /* Day of week */
+       case 0x07:              /* Date of month */
+       case 0x08:              /* Month */
+       case 0x09:              /* Year */
+       case 0x32:              /* Century */
+               /* Ignore writes to change alarm */
+               break;
+       case 0x01:              /* Seconds Alarm */
+       case 0x03:              /* Minutes Alarm */
+       case 0x05:              /* Hours Alarm */
+               LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Trying to set alarm");
+               cmos.regs[cmos.reg]=val;
+               break;
+       case 0x0a:              /* Status reg A */
+               cmos.regs[cmos.reg]=val & 0x7f;
+               if ((val & 0x70)!=0x20) LOG(LOG_BIOS,LOG_ERROR)("CMOS Illegal 22 stage divider value");
+               cmos.timer.div=(val & 0xf);
+               cmos_checktimer();
+               break;
+       case 0x0b:              /* Status reg B */
+               cmos.bcd=!(val & 0x4);
+               cmos.regs[cmos.reg]=val & 0x7f;
+               cmos.timer.enabled=(val & 0x40)>0;
+               if (val&0x10) LOG(LOG_BIOS,LOG_ERROR)("CMOS:Updated ended interrupt not supported yet");
+               cmos_checktimer();
+               break;
+       case 0x0d:/* Status reg D */
+               cmos.regs[cmos.reg]=val & 0x80; /*Bit 7=1:RTC Pown on*/
+               break;
+       case 0x0f:              /* Shutdown status byte */
+               cmos.regs[cmos.reg]=val;// & 0x7f;
+               break;
+       default:
+               cmos.regs[cmos.reg]=val; // & 0x7f;
+               LOG(LOG_BIOS,LOG_ERROR)("CMOS:WRite to unhandled register %x",cmos.reg);
+       }
+}
+
+
+#define MAKE_RETURN(_VAL) (cmos.bcd ? ((((_VAL) / 10) << 4) | ((_VAL) % 10)) : (_VAL));
+
+Bitu cmos_readreg(Bitu port,Bitu iolen) {
+       if (cmos.reg>0x3f) {
+               LOG(LOG_BIOS,LOG_ERROR)("CMOS:Read from illegal register %x",cmos.reg);
+               return 0xff;
+       }
+       Bitu drive_a, drive_b;
+       Bit8u hdparm;
+       time_t curtime;
+       struct tm *loctime;
+       /* Get the current time. */
+       curtime = time (NULL);
+
+       /* Convert it to local time representation. */
+       loctime = localtime (&curtime);
+
+       switch (cmos.reg) {
+       case 0x00:              /* Seconds */
+               return  MAKE_RETURN(loctime->tm_sec);
+       case 0x02:              /* Minutes */
+               return  MAKE_RETURN(loctime->tm_min);
+       case 0x04:              /* Hours */
+               return  MAKE_RETURN(loctime->tm_hour);
+       case 0x06:              /* Day of week */
+               return  MAKE_RETURN(loctime->tm_wday + 1);
+       case 0x07:              /* Date of month */
+               return  MAKE_RETURN(loctime->tm_mday);
+       case 0x08:              /* Month */
+               return  MAKE_RETURN(loctime->tm_mon + 1);
+       case 0x09:              /* Year */
+               return  MAKE_RETURN(loctime->tm_year % 100);
+       case 0x32:              /* Century */
+               return  MAKE_RETURN(loctime->tm_year / 100 + 19);
+       case 0x01:              /* Seconds Alarm */
+       case 0x03:              /* Minutes Alarm */
+       case 0x05:              /* Hours Alarm */
+               return cmos.regs[cmos.reg];
+       case 0x0a:              /* Status register A */
+               if (0 && PIC_TickIndex()<0.002) {
+                       return (cmos.regs[0x0a]&0x7f) | 0x80;
+               } else {
+                       return (cmos.regs[0x0a]&0x7f);
+               }
+       case 0x0c:              /* Status register C */
+               cmos.timer.acknowledged=true;
+               if (cmos.timer.enabled) {
+                       /* In periodic interrupt mode only care for those flags */
+                       Bit8u val=cmos.regs[0xc];
+                       cmos.regs[0xc]=0;
+                       return val;
+               } else {
+                       /* Give correct values at certain times */
+                       Bit8u val=0;
+                       double index=PIC_FullIndex();
+                       if (index>=(cmos.last.timer+cmos.timer.delay)) {
+                               cmos.last.timer=index;
+                               val|=0x40;
+                       } 
+                       if (index>=(cmos.last.ended+1000)) {
+                               cmos.last.ended=index;
+                               val|=0x10;
+                       } 
+                       return val;
+               }
+#if 0
+       case 0x10:              /* Floppy size */
+               drive_a = 0;
+               drive_b = 0;
+               if(imageDiskList[0] != NULL) drive_a = imageDiskList[0]->GetBiosType();
+               if(imageDiskList[1] != NULL) drive_b = imageDiskList[1]->GetBiosType();
+               return ((drive_a << 4) | (drive_b));
+       /* First harddrive info */
+       case 0x12:
+               hdparm = 0;
+               if(imageDiskList[2] != NULL) hdparm |= 0xf;
+               if(imageDiskList[3] != NULL) hdparm |= 0xf0;
+               return hdparm;
+       case 0x19:
+               if(imageDiskList[2] != NULL) return 47; /* User defined type */
+               return 0;
+       case 0x1b:
+               if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff);
+               return 0;
+       case 0x1c:
+               if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8);
+               return 0;
+       case 0x1d:
+               if(imageDiskList[2] != NULL) return (imageDiskList[2]->heads);
+               return 0;
+       case 0x1e:
+               if(imageDiskList[2] != NULL) return 0xff;
+               return 0;
+       case 0x1f:
+               if(imageDiskList[2] != NULL) return 0xff;
+               return 0;
+       case 0x20:
+               if(imageDiskList[2] != NULL) return (0xc0 | (((imageDiskList[2]->heads) > 8) << 3));
+               return 0;
+       case 0x21:
+               if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff);
+               return 0;
+       case 0x22:
+               if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8);
+               return 0;
+       case 0x23:
+               if(imageDiskList[2] != NULL) return (imageDiskList[2]->sectors);
+               return 0;
+       /* Second harddrive info */
+       case 0x1a:
+               if(imageDiskList[3] != NULL) return 47; /* User defined type */
+               return 0;
+       case 0x24:
+               if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff);
+               return 0;
+       case 0x25:
+               if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8);
+               return 0;
+       case 0x26:
+               if(imageDiskList[3] != NULL) return (imageDiskList[3]->heads);
+               return 0;
+       case 0x27:
+               if(imageDiskList[3] != NULL) return 0xff;
+               return 0;
+       case 0x28:
+               if(imageDiskList[3] != NULL) return 0xff;
+               return 0;
+       case 0x29:
+               if(imageDiskList[3] != NULL) return (0xc0 | (((imageDiskList[3]->heads) > 8) << 3));
+               return 0;
+       case 0x2a:
+               if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff);
+               return 0;
+       case 0x2b:
+               if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8);
+               return 0;
+       case 0x2c:
+               if(imageDiskList[3] != NULL) return (imageDiskList[3]->sectors);
+               return 0;
+#endif
+       case 0x39:
+               return 0;
+       case 0x3a:
+               return 0;
+
+
+       case 0x0b:              /* Status register B */
+       case 0x0d:              /* Status register D */
+       case 0x0f:              /* Shutdown status byte */
+       case 0x14:              /* Equipment */
+       case 0x15:              /* Base Memory KB Low Byte */
+       case 0x16:              /* Base Memory KB High Byte */
+       case 0x17:              /* Extended memory in KB Low Byte */
+       case 0x18:              /* Extended memory in KB High Byte */
+       case 0x30:              /* Extended memory in KB Low Byte */
+       case 0x31:              /* Extended memory in KB High Byte */
+//             LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X : %04X",cmos.reg,cmos.regs[cmos.reg]);
+               return cmos.regs[cmos.reg];
+       default:
+               LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X",cmos.reg);
+               return cmos.regs[cmos.reg];
+       }
+}
+
+void CMOS_SetRegister(Bitu regNr, Bit8u val) {
+       cmos.regs[regNr] = val;
+}
+
+
+class CMOS:public Module_base{
+private:
+//     IO_ReadHandleObject ReadHandler[2];
+//     IO_WriteHandleObject WriteHandler[2];   
+public:
+       CMOS(Section* configuration):Module_base(configuration){
+//             WriteHandler[0].Install(0x70,cmos_selreg,IO_MB);
+//             WriteHandler[1].Install(0x71,cmos_writereg,IO_MB);
+//             ReadHandler[0].Install(0x71,cmos_readreg,IO_MB);
+               cmos.timer.enabled=false;
+               cmos.timer.acknowledged=true;
+               cmos.reg=0xa;
+               cmos_writereg(0x71,0x26,1);
+               cmos.reg=0xb;
+               cmos_writereg(0x71,0x2,1);      //Struct tm *loctime is of 24 hour format,
+               cmos.reg=0xd;
+               cmos_writereg(0x71,0x80,1); /* RTC power on */
+               // Equipment is updated from bios.cpp and bios_disk.cpp
+               /* Fill in base memory size, it is 640K always */
+               cmos.regs[0x15]=(Bit8u)0x80;
+               cmos.regs[0x16]=(Bit8u)0x02;
+               /* Fill in extended memory size */
+               Bitu exsize=(MEM_TotalPages()*4)-1024;
+               cmos.regs[0x17]=(Bit8u)exsize;
+               cmos.regs[0x18]=(Bit8u)(exsize >> 8);
+               cmos.regs[0x30]=(Bit8u)exsize;
+               cmos.regs[0x31]=(Bit8u)(exsize >> 8);
+       }
+};
+
+static CMOS* test;
+
+void CMOS_Destroy(Section* sec){
+       delete test;
+}
+
+void CMOS_Init(Section* sec) {
+       test = new CMOS(sec);
+       sec->AddDestroyFunction(&CMOS_Destroy,true);
+}
diff --git a/dosbox/core_full.cpp b/dosbox/core_full.cpp
new file mode 100644 (file)
index 0000000..fe2f2d3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  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.
+ */
+
+#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/dosbox/core_full/ea_lookup.h b/dosbox/core_full/ea_lookup.h
new file mode 100644 (file)
index 0000000..cd8834e
--- /dev/null
@@ -0,0 +1,237 @@
+{
+       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/dosbox/core_full/load.h b/dosbox/core_full/load.h
new file mode 100644 (file)
index 0000000..a5e7ade
--- /dev/null
@@ -0,0 +1,489 @@
+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;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry);
+               goto illegalopcode;
+}
+
diff --git a/dosbox/core_full/loadwrite.h b/dosbox/core_full/loadwrite.h
new file mode 100644 (file)
index 0000000..aca53c4
--- /dev/null
@@ -0,0 +1,39 @@
+#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/dosbox/core_full/op.h b/dosbox/core_full/op.h
new file mode 100644 (file)
index 0000000..5e4114e
--- /dev/null
@@ -0,0 +1,651 @@
+/* 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
+               if (x86_fpu_enabled) {
+                       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/dosbox/core_full/optable.h b/dosbox/core_full/optable.h
new file mode 100644 (file)
index 0000000..a938a8f
--- /dev/null
@@ -0,0 +1,814 @@
+/* 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              },{0            ,0                      ,0              ,0              },
+{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              },{0            ,0                      ,0              ,0              },
+{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/dosbox/core_full/save.h b/dosbox/core_full/save.h
new file mode 100644 (file)
index 0000000..4e10db1
--- /dev/null
@@ -0,0 +1,99 @@
+/* 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/dosbox/core_full/string.h b/dosbox/core_full/string.h
new file mode 100644 (file)
index 0000000..5da65b1
--- /dev/null
@@ -0,0 +1,227 @@
+{
+       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_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/dosbox/core_full/support.h b/dosbox/core_full/support.h
new file mode 100644 (file)
index 0000000..7a0c4dc
--- /dev/null
@@ -0,0 +1,249 @@
+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,
+       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/dosbox/core_normal.cpp b/dosbox/core_normal.cpp
new file mode 100644 (file)
index 0000000..7f3b25b
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  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.
+ */
+
+#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/dosbox/core_normal/helpers.h b/dosbox/core_normal/helpers.h
new file mode 100644 (file)
index 0000000..f0fb75c
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  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.
+ */
+
+
+#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/dosbox/core_normal/prefix_0f.h b/dosbox/core_normal/prefix_0f.h
new file mode 100644 (file)
index 0000000..1c191b5
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ *  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.
+ */
+
+       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;
+                       Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)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/dosbox/core_normal/prefix_66.h b/dosbox/core_normal/prefix_66.h
new file mode 100644 (file)
index 0000000..b9adacc
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ *  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.
+ */
+
+       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/dosbox/core_normal/prefix_66_0f.h b/dosbox/core_normal/prefix_66_0f.h
new file mode 100644 (file)
index 0000000..eed5bac
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ *  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.
+ */
+
+       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/dosbox/core_normal/prefix_none.h b/dosbox/core_normal/prefix_none.h
new file mode 100644 (file)
index 0000000..e374cc9
--- /dev/null
@@ -0,0 +1,1224 @@
+/*
+ *  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.
+ */
+
+       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 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(0);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+               break;
+       CASE_B(0xd9)                                                                                            /* FPU ESC 1 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(1);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xda)                                                                                            /* FPU ESC 2 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(2);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xdb)                                                                                            /* FPU ESC 3 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(3);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xdc)                                                                                            /* FPU ESC 4 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(4);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xdd)                                                                                            /* FPU ESC 5 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(5);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xde)                                                                                            /* FPU ESC 6 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(6);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       break;
+       CASE_B(0xdf)                                                                                            /* FPU ESC 7 */
+               if (x86_fpu_enabled) {
+                       FPU_ESC(7);
+               } else {
+                       Bit8u rm = Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+       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_al=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/dosbox/core_normal/string.h b/dosbox/core_normal/string.h
new file mode 100644 (file)
index 0000000..6fdfc7b
--- /dev/null
@@ -0,0 +1,232 @@
+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_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/dosbox/core_normal/support.h b/dosbox/core_normal/support.h
new file mode 100644 (file)
index 0000000..9b23081
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  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.
+ */
+
+
+#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/dosbox/core_normal/table_ea.h b/dosbox/core_normal/table_ea.h
new file mode 100644 (file)
index 0000000..08d4613
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  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.
+ */
+
+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/dosbox/core_simple.cpp b/dosbox/core_simple.cpp
new file mode 100644 (file)
index 0000000..2d026b9
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  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.
+ */
+
+#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/dosbox/cpu.cpp b/dosbox/cpu.cpp
new file mode 100644 (file)
index 0000000..ea037e3
--- /dev/null
@@ -0,0 +1,2428 @@
+/*
+ *  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: cpu.cpp,v 1.116 2009-03-16 18:10:08 c2woody Exp $ */
+
+#include <assert.h>
+#include <sstream>
+#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_flag_id_toggle=0;
+
+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_flag_id_toggle;       // ID-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:
+                       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:
+                       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:
+                               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:
+               {
+                       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 switched to max cycles, because of the setting: cycles=auto. If 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_Cycles=0;
+       }
+       return 0;
+}
+
+void CPU_HLT(Bitu oldeip) {
+       reg_eip=oldeip;
+       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;
+
+#if 0
+               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"));
+#endif
+               CommandLine cmd(0, NULL);
+               std::string str;
+               std::string type = "max";
+               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"));
+               std::string core = "simple";
+               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"));
+               std::string cputype = "auto";
+               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_flag_id_toggle=FLAG_ID;
+               else CPU_flag_id_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;
+       test = NULL;
+}
+
+void CPU_Init(Section* sec) {
+       test = new CPU(sec);
+       sec->AddDestroyFunction(&CPU_ShutDown,true);
+}
+//initialize static members
+bool CPU::inited=false;
diff --git a/dosbox/cpu.h b/dosbox/cpu.h
new file mode 100644 (file)
index 0000000..d18caa2
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ *  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: cpu.h,v 1.57 2009-05-27 09:15:40 qbix79 Exp $ */
+
+#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         100
+
+
+#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/dosbox/db_memory.cpp b/dosbox/db_memory.cpp
new file mode 100644 (file)
index 0000000..4bb885d
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ *  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: memory.cpp,v 1.56 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#include "dosbox.h"
+#include "mem.h"
+#include "inout.h"
+#include "setup.h"
+#include "paging.h"
+#include "regs.h"
+
+#include <string.h>
+
+#define PAGES_IN_BLOCK ((1024*1024)/MEM_PAGE_SIZE)
+#define SAFE_MEMORY    32
+#define MAX_MEMORY     64
+#define MAX_PAGE_ENTRIES (MAX_MEMORY*1024*1024/4096)
+#define LFB_PAGES      512
+#define MAX_LINKS      ((MAX_MEMORY*1024/4)+4096)              //Hopefully enough
+
+struct LinkBlock {
+       Bitu used;
+       Bit32u pages[MAX_LINKS];
+};
+
+static struct MemoryBlock {
+       Bitu pages;
+       PageHandler * * phandlers;
+       MemHandle * mhandles;
+       LinkBlock links;
+       struct  {
+               Bitu            start_page;
+               Bitu            end_page;
+               Bitu            pages;
+               PageHandler *handler;
+               PageHandler *mmiohandler;
+       } lfb;
+       struct {
+               bool enabled;
+               Bit8u controlport;
+       } a20;
+} memory;
+
+HostPt MemBase;
+
+class IllegalPageHandler : public PageHandler {
+public:
+       IllegalPageHandler() {
+               flags=PFLAG_INIT|PFLAG_NOCODE;
+       }
+       Bitu readb(PhysPt addr) {
+#if C_DEBUG
+               LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip);
+#else
+               static Bits lcount=0;
+               if (lcount<1000) {
+                       lcount++;
+                       LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip);
+               }
+#endif
+               return 0;
+       } 
+       void writeb(PhysPt addr,Bitu val) {
+#if C_DEBUG
+               LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip);
+#else
+               static Bits lcount=0;
+               if (lcount<1000) {
+                       lcount++;
+                       LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip);
+               }
+#endif
+       }
+};
+
+class RAMPageHandler : public PageHandler {
+public:
+       RAMPageHandler() {
+               flags=PFLAG_READABLE|PFLAG_WRITEABLE;
+       }
+       HostPt GetHostReadPt(Bitu phys_page) {
+               return MemBase+phys_page*MEM_PAGESIZE;
+       }
+       HostPt GetHostWritePt(Bitu phys_page) {
+               return MemBase+phys_page*MEM_PAGESIZE;
+       }
+};
+
+class ROMPageHandler : public RAMPageHandler {
+public:
+       ROMPageHandler() {
+               flags=PFLAG_READABLE|PFLAG_HASROM;
+       }
+       void writeb(PhysPt addr,Bitu val){
+               LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr);
+       }
+       void writew(PhysPt addr,Bitu val){
+               LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr);
+       }
+       void writed(PhysPt addr,Bitu val){
+               LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr);
+       }
+};
+
+
+
+static IllegalPageHandler illegal_page_handler;
+static RAMPageHandler ram_page_handler;
+static ROMPageHandler rom_page_handler;
+
+void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler) {
+       memory.lfb.handler=handler;
+       memory.lfb.mmiohandler=mmiohandler;
+       memory.lfb.start_page=page;
+       memory.lfb.end_page=page+pages;
+       memory.lfb.pages=pages;
+       PAGING_ClearTLB();
+}
+
+PageHandler * MEM_GetPageHandler(Bitu phys_page) {
+       if (phys_page<memory.pages) {
+               return memory.phandlers[phys_page];
+       } else if ((phys_page>=memory.lfb.start_page) && (phys_page<memory.lfb.end_page)) {
+               return memory.lfb.handler;
+       } else if ((phys_page>=memory.lfb.start_page+0x01000000/4096) &&
+                               (phys_page<memory.lfb.start_page+0x01000000/4096+16)) {
+               return memory.lfb.mmiohandler;
+       }
+       return &illegal_page_handler;
+}
+
+void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler) {
+       for (;pages>0;pages--) {
+               memory.phandlers[phys_page]=handler;
+               phys_page++;
+       }
+}
+
+void MEM_ResetPageHandler(Bitu phys_page, Bitu pages) {
+       for (;pages>0;pages--) {
+               memory.phandlers[phys_page]=&ram_page_handler;
+               phys_page++;
+       }
+}
+
+Bitu mem_strlen(PhysPt pt) {
+       Bitu x=0;
+       while (x<1024) {
+               if (!mem_readb_inline(pt+x)) return x;
+               x++;
+       }
+       return 0;               //Hope this doesn't happen
+}
+
+void mem_strcpy(PhysPt dest,PhysPt src) {
+       Bit8u r;
+       while ( (r = mem_readb(src++)) ) mem_writeb_inline(dest++,r);
+       mem_writeb_inline(dest,0);
+}
+
+void mem_memcpy(PhysPt dest,PhysPt src,Bitu size) {
+       while (size--) mem_writeb_inline(dest++,mem_readb_inline(src++));
+}
+
+void MEM_BlockRead(PhysPt pt,void * data,Bitu size) {
+       Bit8u * write=reinterpret_cast<Bit8u *>(data);
+       while (size--) {
+               *write++=mem_readb_inline(pt++);
+       }
+}
+
+void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size) {
+       Bit8u const * read = reinterpret_cast<Bit8u const * const>(data);
+       while (size--) {
+               mem_writeb_inline(pt++,*read++);
+       }
+}
+
+void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) {
+       mem_memcpy(dest,src,size);
+}
+
+void MEM_StrCopy(PhysPt pt,char * data,Bitu size) {
+       while (size--) {
+               Bit8u r=mem_readb_inline(pt++);
+               if (!r) break;
+               *data++=r;
+       }
+       *data=0;
+}
+
+Bitu MEM_TotalPages(void) {
+       return memory.pages;
+}
+
+Bitu MEM_FreeLargest(void) {
+       Bitu size=0;Bitu largest=0;
+       Bitu index=XMS_START;   
+       while (index<memory.pages) {
+               if (!memory.mhandles[index]) {
+                       size++;
+               } else {
+                       if (size>largest) largest=size;
+                       size=0;
+               }
+               index++;
+       }
+       if (size>largest) largest=size;
+       return largest;
+}
+
+Bitu MEM_FreeTotal(void) {
+       Bitu free=0;
+       Bitu index=XMS_START;   
+       while (index<memory.pages) {
+               if (!memory.mhandles[index]) free++;
+               index++;
+       }
+       return free;
+}
+
+Bitu MEM_AllocatedPages(MemHandle handle) 
+{
+       Bitu pages = 0;
+       while (handle>0) {
+               pages++;
+               handle=memory.mhandles[handle];
+       }
+       return pages;
+}
+
+//TODO Maybe some protection for this whole allocation scheme
+
+INLINE Bitu BestMatch(Bitu size) {
+       Bitu index=XMS_START;   
+       Bitu first=0;
+       Bitu best=0xfffffff;
+       Bitu best_first=0;
+       while (index<memory.pages) {
+               /* Check if we are searching for first free page */
+               if (!first) {
+                       /* Check if this is a free page */
+                       if (!memory.mhandles[index]) {
+                               first=index;    
+                       }
+               } else {
+                       /* Check if this still is used page */
+                       if (memory.mhandles[index]) {
+                               Bitu pages=index-first;
+                               if (pages==size) {
+                                       return first;
+                               } else if (pages>size) {
+                                       if (pages<best) {
+                                               best=pages;
+                                               best_first=first;
+                                       }
+                               }
+                               first=0;                        //Always reset for new search
+                       }
+               }
+               index++;
+       }
+       /* Check for the final block if we can */
+       if (first && (index-first>=size) && (index-first<best)) {
+               return first;
+       }
+       return best_first;
+}
+
+MemHandle MEM_AllocatePages(Bitu pages,bool sequence) {
+       MemHandle ret;
+       if (!pages) return 0;
+       if (sequence) {
+               Bitu index=BestMatch(pages);
+               if (!index) return 0;
+               MemHandle * next=&ret;
+               while (pages) {
+                       *next=index;
+                       next=&memory.mhandles[index];
+                       index++;pages--;
+               }
+               *next=-1;
+       } else {
+               if (MEM_FreeTotal()<pages) return 0;
+               MemHandle * next=&ret;
+               while (pages) {
+                       Bitu index=BestMatch(1);
+                       if (!index) E_Exit("MEM:corruption during allocate");
+                       while (pages && (!memory.mhandles[index])) {
+                               *next=index;
+                               next=&memory.mhandles[index];
+                               index++;pages--;
+                       }
+                       *next=-1;               //Invalidate it in case we need another match
+               }
+       }
+       return ret;
+}
+
+MemHandle MEM_GetNextFreePage(void) {
+       return (MemHandle)BestMatch(1);
+}
+
+void MEM_ReleasePages(MemHandle handle) {
+       while (handle>0) {
+               MemHandle next=memory.mhandles[handle];
+               memory.mhandles[handle]=0;
+               handle=next;
+       }
+}
+
+bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) {
+       if (handle<=0) {
+               if (!pages) return true;
+               handle=MEM_AllocatePages(pages,sequence);
+               return (handle>0);
+       }
+       if (!pages) {
+               MEM_ReleasePages(handle);
+               handle=-1;
+               return true;
+       }
+       MemHandle index=handle;
+       MemHandle last;Bitu old_pages=0;
+       while (index>0) {
+               old_pages++;
+               last=index;
+               index=memory.mhandles[index];
+       }
+       if (old_pages == pages) return true;
+       if (old_pages > pages) {
+               /* Decrease size */
+               pages--;index=handle;old_pages--;
+               while (pages) {
+                       index=memory.mhandles[index];
+                       pages--;old_pages--;
+               }
+               MemHandle next=memory.mhandles[index];
+               memory.mhandles[index]=-1;
+               index=next;
+               while (old_pages) {
+                       next=memory.mhandles[index];
+                       memory.mhandles[index]=0;
+                       index=next;
+                       old_pages--;
+               }
+               return true;
+       } else {
+               /* Increase size, check for enough free space */
+               Bitu need=pages-old_pages;
+               if (sequence) {
+                       index=last+1;
+                       Bitu free=0;
+                       while ((index<(MemHandle)memory.pages) && !memory.mhandles[index]) {
+                               index++;free++;
+                       }
+                       if (free>=need) {
+                               /* Enough space allocate more pages */
+                               index=last;
+                               while (need) {
+                                       memory.mhandles[index]=index+1;
+                                       need--;index++;
+                               }
+                               memory.mhandles[index]=-1;
+                               return true;
+                       } else {
+                               /* Not Enough space allocate new block and copy */
+                               MemHandle newhandle=MEM_AllocatePages(pages,true);
+                               if (!newhandle) return false;
+                               MEM_BlockCopy(newhandle*4096,handle*4096,old_pages*4096);
+                               MEM_ReleasePages(handle);
+                               handle=newhandle;
+                               return true;
+                       }
+               } else {
+                       MemHandle rem=MEM_AllocatePages(need,false);
+                       if (!rem) return false;
+                       memory.mhandles[last]=rem;
+                       return true;
+               }
+       }
+       return 0;
+}
+
+MemHandle MEM_NextHandle(MemHandle handle) {
+       return memory.mhandles[handle];
+}
+
+MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where) {
+       while (where) {
+               where--;        
+               handle=memory.mhandles[handle];
+       }
+       return handle;
+}
+
+
+/* 
+       A20 line handling, 
+       Basically maps the 4 pages at the 1mb to 0mb in the default page directory
+*/
+bool MEM_A20_Enabled(void) {
+       return memory.a20.enabled;
+}
+
+void MEM_A20_Enable(bool enabled) {
+       Bitu phys_base=enabled ? (1024/4) : 0;
+       for (Bitu i=0;i<16;i++) PAGING_MapPage((1024/4)+i,phys_base+i);
+       memory.a20.enabled=enabled;
+}
+
+
+/* Memory access functions */
+Bit16u mem_unalignedreadw(PhysPt address) {
+       return mem_readb_inline(address) |
+               mem_readb_inline(address+1) << 8;
+}
+
+Bit32u mem_unalignedreadd(PhysPt address) {
+       return mem_readb_inline(address) |
+               (mem_readb_inline(address+1) << 8) |
+               (mem_readb_inline(address+2) << 16) |
+               (mem_readb_inline(address+3) << 24);
+}
+
+
+void mem_unalignedwritew(PhysPt address,Bit16u val) {
+       mem_writeb_inline(address,(Bit8u)val);val>>=8;
+       mem_writeb_inline(address+1,(Bit8u)val);
+}
+
+void mem_unalignedwrited(PhysPt address,Bit32u val) {
+       mem_writeb_inline(address,(Bit8u)val);val>>=8;
+       mem_writeb_inline(address+1,(Bit8u)val);val>>=8;
+       mem_writeb_inline(address+2,(Bit8u)val);val>>=8;
+       mem_writeb_inline(address+3,(Bit8u)val);
+}
+
+
+bool mem_unalignedreadw_checked(PhysPt address, Bit16u * val) {
+       Bit8u rval1,rval2;
+       if (mem_readb_checked(address+0, &rval1)) return true;
+       if (mem_readb_checked(address+1, &rval2)) return true;
+       *val=(Bit16u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8));
+       return false;
+}
+
+bool mem_unalignedreadd_checked(PhysPt address, Bit32u * val) {
+       Bit8u rval1,rval2,rval3,rval4;
+       if (mem_readb_checked(address+0, &rval1)) return true;
+       if (mem_readb_checked(address+1, &rval2)) return true;
+       if (mem_readb_checked(address+2, &rval3)) return true;
+       if (mem_readb_checked(address+3, &rval4)) return true;
+       *val=(Bit32u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8) | (((Bit8u)rval3) << 16) | (((Bit8u)rval4) << 24));
+       return false;
+}
+
+bool mem_unalignedwritew_checked(PhysPt address,Bit16u val) {
+       if (mem_writeb_checked(address,(Bit8u)(val & 0xff))) return true;val>>=8;
+       if (mem_writeb_checked(address+1,(Bit8u)(val & 0xff))) return true;
+       return false;
+}
+
+bool mem_unalignedwrited_checked(PhysPt address,Bit32u val) {
+       if (mem_writeb_checked(address,(Bit8u)(val & 0xff))) return true;val>>=8;
+       if (mem_writeb_checked(address+1,(Bit8u)(val & 0xff))) return true;val>>=8;
+       if (mem_writeb_checked(address+2,(Bit8u)(val & 0xff))) return true;val>>=8;
+       if (mem_writeb_checked(address+3,(Bit8u)(val & 0xff))) return true;
+       return false;
+}
+
+Bit8u mem_readb(PhysPt address) {
+       return mem_readb_inline(address);
+}
+
+Bit16u mem_readw(PhysPt address) {
+       return mem_readw_inline(address);
+}
+
+Bit32u mem_readd(PhysPt address) {
+       return mem_readd_inline(address);
+}
+
+void mem_writeb(PhysPt address,Bit8u val) {
+       mem_writeb_inline(address,val);
+}
+
+void mem_writew(PhysPt address,Bit16u val) {
+       mem_writew_inline(address,val);
+}
+
+void mem_writed(PhysPt address,Bit32u val) {
+       mem_writed_inline(address,val);
+}
+
+static void write_p92(Bitu port,Bitu val,Bitu iolen) { 
+       // Bit 0 = system reset (switch back to real mode)
+       if (val&1) E_Exit("XMS: CPU reset via port 0x92 not supported.");
+       memory.a20.controlport = val & ~2;
+       MEM_A20_Enable((val & 2)>0);
+}
+
+static Bitu read_p92(Bitu port,Bitu iolen) {
+       return memory.a20.controlport | (memory.a20.enabled ? 0x02 : 0);
+}
+
+void RemoveEMSPageFrame(void) {
+       /* Setup rom at 0xe0000-0xf0000 */
+       for (Bitu ct=0xe0;ct<0xf0;ct++) {
+               memory.phandlers[ct] = &rom_page_handler;
+       }
+}
+
+void PreparePCJRCartRom(void) {
+       /* Setup rom at 0xd0000-0xe0000 */
+       for (Bitu ct=0xd0;ct<0xe0;ct++) {
+               memory.phandlers[ct] = &rom_page_handler;
+       }
+}
+
+HostPt GetMemBase(void) { return MemBase; }
+
+extern int x86_memsize;
+extern int x86_biosstart;
+
+class MEMORY:public Module_base{
+#if 0
+private:
+       IO_ReadHandleObject ReadHandler;
+       IO_WriteHandleObject WriteHandler;
+#endif
+public:        
+       MEMORY(Section* configuration):Module_base(configuration){
+               Bitu i;
+               Section_prop * section=static_cast<Section_prop *>(configuration);
+       
+               /* Setup the Physical Page Links */
+#if 0
+               Bitu memsize=section->Get_int("memsize");
+#else
+               Bitu memsize = x86_memsize / (1024 * 1024);
+#endif
+               if (memsize < 1) memsize = 1;
+               /* max 63 to solve problems with certain xms handlers */
+               if (memsize > MAX_MEMORY-1) {
+                       LOG_MSG("Maximum memory size is %d MB",MAX_MEMORY - 1);
+                       memsize = MAX_MEMORY-1;
+               }
+               if (memsize > SAFE_MEMORY-1) {
+                       LOG_MSG("Memory sizes above %d MB are NOT recommended.",SAFE_MEMORY - 1);
+                       LOG_MSG("Stick with the default values unless you are absolutely certain.");
+               }
+#if 0
+               MemBase = new Bit8u[memsize*1024*1024];
+               if (!MemBase) E_Exit("Can't allocate main memory of %d MB",memsize);
+               /* Clear the memory, as new doesn't always give zeroed memory
+                * (Visual C debug mode). We want zeroed memory though. */
+               memset((void*)MemBase,0,memsize*1024*1024);
+#endif
+               memory.pages = (memsize*1024*1024)/4096;
+               /* Allocate the data for the different page information blocks */
+               memory.phandlers=new  PageHandler * [memory.pages];
+               memory.mhandles=new MemHandle [memory.pages];
+               for (i = 0;i < memory.pages;i++) {
+                       memory.phandlers[i] = &ram_page_handler;
+                       memory.mhandles[i] = 0;                         //Set to 0 for memory allocation
+               }
+#if 0
+               /* Setup rom at 0xc0000-0xc8000 */
+               for (i=0xc0;i<0xc8;i++) {
+                       memory.phandlers[i] = &rom_page_handler;
+               }
+#endif
+               /* Setup rom at 0xf0000-0x100000 */
+               for (i= (x86_biosstart >> 12);i<0x100;i++) {
+                       memory.phandlers[i] = &rom_page_handler;
+               }
+#if 0
+               if (machine==MCH_PCJR) {
+                       /* Setup cartridge rom at 0xe0000-0xf0000 */
+                       for (i=0xe0;i<0xf0;i++) {
+                               memory.phandlers[i] = &rom_page_handler;
+                       }
+               }
+#endif
+               /* Reset some links */
+               memory.links.used = 0;
+#if 0
+               // A20 Line - PS/2 system control port A
+               WriteHandler.Install(0x92,write_p92,IO_MB);
+               ReadHandler.Install(0x92,read_p92,IO_MB);
+#endif
+               MEM_A20_Enable(false);
+       }
+       ~MEMORY(){
+               //delete [] MemBase;
+               delete [] memory.phandlers;
+               delete [] memory.mhandles;
+       }
+};     
+
+       
+static MEMORY* test;   
+       
+void MEM_ShutDown(Section * sec) {
+       delete test;
+}
+
+void MEM_Init(Section * sec) {
+       /* shutdown function */
+       test = new MEMORY(sec);
+       sec->AddDestroyFunction(&MEM_ShutDown);
+}
diff --git a/dosbox/dosbox.h b/dosbox/dosbox.h
new file mode 100644 (file)
index 0000000..e76e0c9
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef DOSBOX_H
+#define DOSBOX_H
+
+#ifndef CH_LIST
+#define CH_LIST
+#include <list>
+#endif
+
+#ifndef CH_STRING
+#define CH_STRING
+#include <string>
+#endif
+
+#define C_FPU 1
+
+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
+typedef Bit32u Bitu;
+typedef Bit32s Bits;
+typedef double Real64;
+
+#define LONGTYPE(a) a##LL
+
+#define INLINE __inline
+
+#define GCC_ATTRIBUTE(x)
+
+#include "logging.h"
+
+extern void E_Exit(char*,...);
+extern void DOSBOX_RunMachine(void);
+
+#define GCC_UNLIKELY(x) x
+#define GCC_LIKELY(x) x
+
+#define MAPPER_AddHandler(x1,x2,x3,x4,x5)
+
+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 GetStringRemain(std::string & value);
+       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);
+};
+
+extern int x86_fpu_enabled;
+
+#endif
diff --git a/dosbox/flags.cpp b/dosbox/flags.cpp
new file mode 100644 (file)
index 0000000..2e9532f
--- /dev/null
@@ -0,0 +1,1188 @@
+/*
+ *  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.
+ */
+
+/*
+       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/dosbox/fpu.cpp b/dosbox/fpu.cpp
new file mode 100644 (file)
index 0000000..6a0cc80
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ *  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: fpu.cpp,v 1.31 2009-09-16 18:01:53 qbix79 Exp $ */
+
+#include "dosbox.h"
+#if C_FPU
+
+#include <math.h>
+#include <float.h>
+#include "setup.h"
+//#include "cross.h"
+#include "mem.h"
+#include "fpu.h"
+#include "cpu.h"
+
+FPU_rec fpu;
+
+void FPU_FLDCW(PhysPt addr){
+       Bit16u temp = mem_readw(addr);
+       FPU_SetCW(temp);
+}
+
+Bit16u FPU_GetTag(void){
+       Bit16u tag=0;
+       for(Bitu i=0;i<8;i++)
+               tag |= ( (fpu.tags[i]&3) <<(2*i));
+       return tag;
+}
+
+#if C_FPU_X86
+#include "fpu_instructions_x86.h"
+#else
+#include "fpu_instructions.h"
+#endif
+
+/* WATCHIT : ALWAYS UPDATE REGISTERS BEFORE AND AFTER USING THEM 
+                       STATUS WORD =>  FPU_SET_TOP(TOP) BEFORE a read
+                       TOP=FPU_GET_TOP() after a write;
+                       */
+
+static void EATREE(Bitu _rm){
+       Bitu group=(_rm >> 3) & 7;
+       switch(group){
+               case 0x00:      /* FADD */
+                       FPU_FADD_EA(TOP);
+                       break;
+               case 0x01:      /* FMUL  */
+                       FPU_FMUL_EA(TOP);
+                       break;
+               case 0x02:      /* FCOM */
+                       FPU_FCOM_EA(TOP);
+                       break;
+               case 0x03:      /* FCOMP */
+                       FPU_FCOM_EA(TOP);
+                       FPU_FPOP();
+                       break;
+               case 0x04:      /* FSUB */
+                       FPU_FSUB_EA(TOP);
+                       break;
+               case 0x05:      /* FSUBR */
+                       FPU_FSUBR_EA(TOP);
+                       break;
+               case 0x06:      /* FDIV */
+                       FPU_FDIV_EA(TOP);
+                       break;
+               case 0x07:      /* FDIVR */
+                       FPU_FDIVR_EA(TOP);
+                       break;
+               default:
+                       break;
+       }
+}
+
+void FPU_ESC0_EA(Bitu rm,PhysPt addr) {
+       /* REGULAR TREE WITH 32 BITS REALS */
+       FPU_FLD_F32_EA(addr);
+       EATREE(rm);
+}
+
+void FPU_ESC0_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch (group){
+       case 0x00:              /* FADD ST,STi */
+               FPU_FADD(TOP,STV(sub));
+               break;
+       case 0x01:              /* FMUL  ST,STi */
+               FPU_FMUL(TOP,STV(sub));
+               break;
+       case 0x02:              /* FCOM  STi */
+               FPU_FCOM(TOP,STV(sub));
+               break;
+       case 0x03:              /* FCOMP STi */
+               FPU_FCOM(TOP,STV(sub));
+               FPU_FPOP();
+               break;
+       case 0x04:              /* FSUB  ST,STi */
+               FPU_FSUB(TOP,STV(sub));
+               break;  
+       case 0x05:              /* FSUBR ST,STi */
+               FPU_FSUBR(TOP,STV(sub));
+               break;
+       case 0x06:              /* FDIV  ST,STi */
+               FPU_FDIV(TOP,STV(sub));
+               break;
+       case 0x07:              /* FDIVR ST,STi */
+               FPU_FDIVR(TOP,STV(sub));
+               break;
+       default:
+               break;
+       }
+}
+
+void FPU_ESC1_EA(Bitu rm,PhysPt addr) {
+// floats
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00: /* FLD float*/
+               FPU_PREP_PUSH();
+               FPU_FLD_F32(addr,TOP);
+               break;
+       case 0x01: /* UNKNOWN */
+               LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+               break;
+       case 0x02: /* FST float*/
+               FPU_FST_F32(addr);
+               break;
+       case 0x03: /* FSTP float*/
+               FPU_FST_F32(addr);
+               FPU_FPOP();
+               break;
+       case 0x04: /* FLDENV */
+               FPU_FLDENV(addr);
+               break;
+       case 0x05: /* FLDCW */
+               FPU_FLDCW(addr);
+               break;
+       case 0x06: /* FSTENV */
+               FPU_FSTENV(addr);
+               break;
+       case 0x07:  /* FNSTCW*/
+               mem_writew(addr,fpu.cw);
+               break;
+       default:
+               LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+               break;
+       }
+}
+
+void FPU_ESC1_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch (group){
+       case 0x00: /* FLD STi */
+               {
+                       Bitu reg_from=STV(sub);
+                       FPU_PREP_PUSH();
+                       FPU_FST(reg_from, TOP);
+                       break;
+               }
+       case 0x01: /* FXCH STi */
+               FPU_FXCH(TOP,STV(sub));
+               break;
+       case 0x02: /* FNOP */
+               FPU_FNOP();
+               break;
+       case 0x03: /* FSTP STi */
+               FPU_FST(TOP,STV(sub));
+               FPU_FPOP();
+               break;   
+       case 0x04:
+               switch(sub){
+               case 0x00:       /* FCHS */
+                       FPU_FCHS();
+                       break;
+               case 0x01:       /* FABS */
+                       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 */
+                       FPU_FTST();
+                       break;
+               case 0x05:       /* FXAM */
+                       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 */
+                       FPU_FLD1();
+                       break;
+               case 0x01:       /* FLDL2T */
+                       FPU_FLDL2T();
+                       break;
+               case 0x02:       /* FLDL2E */
+                       FPU_FLDL2E();
+                       break;
+               case 0x03:       /* FLDPI */
+                       FPU_FLDPI();
+                       break;
+               case 0x04:       /* FLDLG2 */
+                       FPU_FLDLG2();
+                       break;
+               case 0x05:       /* FLDLN2 */
+                       FPU_FLDLN2();
+                       break;
+               case 0x06:       /* FLDZ*/
+                       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 */
+                       FPU_F2XM1();
+                       break;
+               case 0x01:      /* FYL2X */
+                       FPU_FYL2X();
+                       break;
+               case 0x02:      /* FPTAN  */
+                       FPU_FPTAN();
+                       break;
+               case 0x03:      /* FPATAN */
+                       FPU_FPATAN();
+                       break;
+               case 0x04:      /* FXTRACT */
+                       FPU_FXTRACT();
+                       break;
+               case 0x05:      /* FPREM1 */
+                       FPU_FPREM1();
+                       break;
+               case 0x06:      /* FDECSTP */
+                       TOP = (TOP - 1) & 7;
+                       break;
+               case 0x07:      /* FINCSTP */
+                       TOP = (TOP + 1) & 7;
+                       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 */
+                       FPU_FPREM();
+                       break;
+               case 0x01:              /* FYL2XP1 */
+                       FPU_FYL2XP1();
+                       break;
+               case 0x02:              /* FSQRT */
+                       FPU_FSQRT();
+                       break;
+               case 0x03:              /* FSINCOS */
+                       FPU_FSINCOS();
+                       break;
+               case 0x04:              /* FRNDINT */
+                       FPU_FRNDINT();
+                       break;
+               case 0x05:              /* FSCALE */
+                       FPU_FSCALE();
+                       break;
+               case 0x06:              /* FSIN */
+                       FPU_FSIN();
+                       break;
+               case 0x07:              /* FCOS */
+                       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);
+       }
+}
+
+
+void FPU_ESC2_EA(Bitu rm,PhysPt addr) {
+       /* 32 bits integer operants */
+       FPU_FLD_I32_EA(addr);
+       EATREE(rm);
+}
+
+void FPU_ESC2_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x05:
+               switch(sub){
+               case 0x01:              /* FUCOMPP */
+                       FPU_FUCOM(TOP,STV(1));
+                       FPU_FPOP();
+                       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;
+       }
+}
+
+
+void FPU_ESC3_EA(Bitu rm,PhysPt addr) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00:      /* FILD */
+               FPU_PREP_PUSH();
+               FPU_FLD_I32(addr,TOP);
+               break;
+       case 0x01:      /* FISTTP */
+               LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+               break;
+       case 0x02:      /* FIST */
+               FPU_FST_I32(addr);
+               break;
+       case 0x03:      /* FISTP */
+               FPU_FST_I32(addr);
+               FPU_FPOP();
+               break;
+       case 0x05:      /* FLD 80 Bits Real */
+               FPU_PREP_PUSH();
+               FPU_FLD_F80(addr);
+               break;
+       case 0x07:      /* FSTP 80 Bits Real */
+               FPU_FST_F80(addr);
+               FPU_FPOP();
+               break;
+       default:
+               LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+       }
+}
+
+void FPU_ESC3_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 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
+                       FPU_FCLEX();
+                       break;
+               case 0x03:                              //FNINIT FINIT
+                       FPU_FINIT();
+                       break;
+               case 0x04:                              //FNSETPM
+               case 0x05:                              //FRSTPM
+//                     LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
+                       FPU_FNOP();
+                       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;
+       }
+       return;
+}
+
+
+void FPU_ESC4_EA(Bitu rm,PhysPt addr) {
+       /* REGULAR TREE WITH 64 BITS REALS */
+       FPU_FLD_F64_EA(addr);
+       EATREE(rm);
+}
+
+void FPU_ESC4_Normal(Bitu rm) {
+       /* LOOKS LIKE number 6 without popping */
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00:      /* FADD STi,ST*/
+               FPU_FADD(STV(sub),TOP);
+               break;
+       case 0x01:      /* FMUL STi,ST*/
+               FPU_FMUL(STV(sub),TOP);
+               break;
+       case 0x02:  /* FCOM*/
+               FPU_FCOM(TOP,STV(sub));
+               break;
+       case 0x03:  /* FCOMP*/
+               FPU_FCOM(TOP,STV(sub));
+               FPU_FPOP();
+               break;
+       case 0x04:  /* FSUBR STi,ST*/
+               FPU_FSUBR(STV(sub),TOP);
+               break;
+       case 0x05:  /* FSUB  STi,ST*/
+               FPU_FSUB(STV(sub),TOP);
+               break;
+       case 0x06:  /* FDIVR STi,ST*/
+               FPU_FDIVR(STV(sub),TOP);
+               break;
+       case 0x07:  /* FDIV STi,ST*/
+               FPU_FDIV(STV(sub),TOP);
+               break;
+       default:
+               break;
+       }
+}
+
+void FPU_ESC5_EA(Bitu rm,PhysPt addr) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00:  /* FLD double real*/
+               FPU_PREP_PUSH();
+               FPU_FLD_F64(addr,TOP);
+               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*/
+               FPU_FST_F64(addr);
+               break;
+       case 0x03:      /* FSTP double real*/
+               FPU_FST_F64(addr);
+               FPU_FPOP();
+               break;
+       case 0x04:      /* FRSTOR */
+               FPU_FRSTOR(addr);
+               break;
+       case 0x06:      /* FSAVE */
+               FPU_FSAVE(addr);
+               break;
+       case 0x07:   /*FNSTSW    NG DISAGREES ON THIS*/
+               FPU_SET_TOP(TOP);
+               mem_writew(addr,fpu.sw);
+               //seems to break all dos4gw games :)
+               break;
+       default:
+               LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
+       }
+}
+
+void FPU_ESC5_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00: /* FFREE STi */
+               fpu.tags[STV(sub)]=TAG_Empty;
+               break;
+       case 0x01: /* FXCH STi*/
+               FPU_FXCH(TOP,STV(sub));
+               break;
+       case 0x02: /* FST STi */
+               FPU_FST(TOP,STV(sub));
+               break;
+       case 0x03:  /* FSTP STi*/
+               FPU_FST(TOP,STV(sub));
+               FPU_FPOP();
+               break;
+       case 0x04:      /* FUCOM STi */
+               FPU_FUCOM(TOP,STV(sub));
+               break;
+       case 0x05:      /*FUCOMP STi */
+               FPU_FUCOM(TOP,STV(sub));
+               FPU_FPOP();
+               break;
+       default:
+       LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub);
+       break;
+       }
+}
+
+void FPU_ESC6_EA(Bitu rm,PhysPt addr) {
+       /* 16 bit (word integer) operants */
+       FPU_FLD_I16_EA(addr);
+       EATREE(rm);
+}
+
+void FPU_ESC6_Normal(Bitu rm) {
+       /* all P variants working only on registers */
+       /* get top before switch and pop afterwards */
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00:      /*FADDP STi,ST*/
+               FPU_FADD(STV(sub),TOP);
+               break;
+       case 0x01:      /* FMULP STi,ST*/
+               FPU_FMUL(STV(sub),TOP);
+               break;
+       case 0x02:  /* FCOMP5*/
+               FPU_FCOM(TOP,STV(sub));
+               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;
+               }
+               FPU_FCOM(TOP,STV(1));
+               FPU_FPOP(); /* extra pop at the bottom*/
+               break;
+       case 0x04:  /* FSUBRP STi,ST*/
+               FPU_FSUBR(STV(sub),TOP);
+               break;
+       case 0x05:  /* FSUBP  STi,ST*/
+               FPU_FSUB(STV(sub),TOP);
+               break;
+       case 0x06:      /* FDIVRP STi,ST*/
+               FPU_FDIVR(STV(sub),TOP);
+               break;
+       case 0x07:  /* FDIVP STi,ST*/
+               FPU_FDIV(STV(sub),TOP);
+               break;
+       default:
+               break;
+       }
+       FPU_FPOP();             
+}
+
+
+void FPU_ESC7_EA(Bitu rm,PhysPt addr) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch(group){
+       case 0x00:  /* FILD Bit16s */
+               FPU_PREP_PUSH();
+               FPU_FLD_I16(addr,TOP);
+               break;
+       case 0x01:
+               LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+               break;
+       case 0x02:   /* FIST Bit16s */
+               FPU_FST_I16(addr);
+               break;
+       case 0x03:      /* FISTP Bit16s */
+               FPU_FST_I16(addr);
+               FPU_FPOP();
+               break;
+       case 0x04:   /* FBLD packed BCD */
+               FPU_PREP_PUSH();
+               FPU_FBLD(addr,TOP);
+               break;
+       case 0x05:  /* FILD Bit64s */
+               FPU_PREP_PUSH();
+               FPU_FLD_I64(addr,TOP);
+               break;
+       case 0x06:      /* FBSTP packed BCD */
+               FPU_FBST(addr);
+               FPU_FPOP();
+               break;
+       case 0x07:  /* FISTP Bit64s */
+               FPU_FST_I64(addr);
+               FPU_FPOP();
+               break;
+       default:
+               LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+               break;
+       }
+}
+
+void FPU_ESC7_Normal(Bitu rm) {
+       Bitu group=(rm >> 3) & 7;
+       Bitu sub=(rm & 7);
+       switch (group){
+       case 0x00: /* FFREEP STi*/
+               fpu.tags[STV(sub)]=TAG_Empty;
+               FPU_FPOP();
+               break;
+       case 0x01: /* FXCH STi*/
+               FPU_FXCH(TOP,STV(sub));
+               break;
+       case 0x02:  /* FSTP STi*/
+       case 0x03:  /* FSTP STi*/
+               FPU_FST(TOP,STV(sub));
+               FPU_FPOP();
+               break;
+       case 0x04:
+               switch(sub){
+                       case 0x00:     /* FNSTSW AX*/
+                               FPU_SET_TOP(TOP);
+                               reg_ax = fpu.sw;
+                               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;
+       }
+}
+
+
+void FPU_Init(Section*) {
+       FPU_FINIT();
+}
+
+#endif
diff --git a/dosbox/fpu.h b/dosbox/fpu.h
new file mode 100644 (file)
index 0000000..67f7db4
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *  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.
+ */
+
+#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;
+       Bitu            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/dosbox/fpu_instructions.h b/dosbox/fpu_instructions.h
new file mode 100644 (file)
index 0000000..9a505a2
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ *  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: fpu_instructions.h,v 1.33 2009-05-27 09:15:41 qbix79 Exp $ */
+
+
+static void FPU_FINIT(void) {
+       FPU_SetCW(0x37F);
+       fpu.sw = 0;
+       TOP=FPU_GET_TOP();
+       fpu.tags[0] = TAG_Empty;
+       fpu.tags[1] = TAG_Empty;
+       fpu.tags[2] = TAG_Empty;
+       fpu.tags[3] = TAG_Empty;
+       fpu.tags[4] = TAG_Empty;
+       fpu.tags[5] = TAG_Empty;
+       fpu.tags[6] = TAG_Empty;
+       fpu.tags[7] = TAG_Empty;
+       fpu.tags[8] = TAG_Valid; // is only used by us
+}
+
+static void FPU_FCLEX(void){
+       fpu.sw &= 0x7f00;                       //should clear exceptions
+}
+
+static void FPU_FNOP(void){
+       return;
+}
+
+static void FPU_PUSH(double in){
+       TOP = (TOP - 1) &7;
+       //actually check if empty
+       fpu.tags[TOP] = TAG_Valid;
+       fpu.regs[TOP].d = in;
+//     LOG(LOG_FPU,LOG_ERROR)("Pushed at %d  %g to the stack",newtop,in);
+       return;
+}
+
+static void FPU_PREP_PUSH(void){
+       TOP = (TOP - 1) &7;
+       fpu.tags[TOP] = TAG_Valid;
+}
+
+static void FPU_FPOP(void){
+       fpu.tags[TOP]=TAG_Empty;
+       //maybe set zero in it as well
+       TOP = ((TOP+1)&7);
+//     LOG(LOG_FPU,LOG_ERROR)("popped from %d  %g off the stack",top,fpu.regs[top].d);
+       return;
+}
+
+static double FROUND(double in){
+       switch(fpu.round){
+       case ROUND_Nearest:     
+               if (in-floor(in)>0.5) return (floor(in)+1);
+               else if (in-floor(in)<0.5) return (floor(in));
+               else return (((static_cast<Bit64s>(floor(in)))&1)!=0)?(floor(in)+1):(floor(in));
+               break;
+       case ROUND_Down:
+               return (floor(in));
+               break;
+       case ROUND_Up:
+               return (ceil(in));
+               break;
+       case ROUND_Chop:
+               return in; //the cast afterwards will do it right maybe cast here
+               break;
+       default:
+               return in;
+               break;
+       }
+}
+
+#define BIAS80 16383
+#define BIAS64 1023
+
+static Real64 FPU_FLD80(PhysPt addr) {
+       struct {
+               Bit16s begin;
+               FPU_Reg eind;
+       } test;
+       test.eind.l.lower = mem_readd(addr);
+       test.eind.l.upper = mem_readd(addr+4);
+       test.begin = mem_readw(addr+8);
+
+       Bit64s exp64 = (((test.begin&0x7fff) - BIAS80));
+       Bit64s blah = ((exp64 >0)?exp64:-exp64)&0x3ff;
+       Bit64s exp64final = ((exp64 >0)?blah:-blah) +BIAS64;
+
+       Bit64s mant64 = (test.eind.ll >> 11) & LONGTYPE(0xfffffffffffff);
+       Bit64s sign = (test.begin&0x8000)?1:0;
+       FPU_Reg result;
+       result.ll = (sign <<63)|(exp64final << 52)| mant64;
+       return result.d;
+
+       //mant64= test.mant80/2***64    * 2 **53 
+}
+
+static void FPU_ST80(PhysPt addr,Bitu reg) {
+       struct {
+               Bit16s begin;
+               FPU_Reg eind;
+       } test;
+       Bit64s sign80 = (fpu.regs[reg].ll&LONGTYPE(0x8000000000000000))?1:0;
+       Bit64s exp80 =  fpu.regs[reg].ll&LONGTYPE(0x7ff0000000000000);
+       Bit64s exp80final = (exp80>>52);
+       Bit64s mant80 = fpu.regs[reg].ll&LONGTYPE(0x000fffffffffffff);
+       Bit64s mant80final = (mant80 << 11);
+       if(fpu.regs[reg].d != 0){ //Zero is a special case
+               // Elvira wants the 8 and tcalc doesn't
+               mant80final |= LONGTYPE(0x8000000000000000);
+               //Ca-cyber doesn't like this when result is zero.
+               exp80final += (BIAS80 - BIAS64);
+       }
+       test.begin = (static_cast<Bit16s>(sign80)<<15)| static_cast<Bit16s>(exp80final);
+       test.eind.ll = mant80final;
+       mem_writed(addr,test.eind.l.lower);
+       mem_writed(addr+4,test.eind.l.upper);
+       mem_writew(addr+8,test.begin);
+}
+
+
+static void FPU_FLD_F32(PhysPt addr,Bitu store_to) {
+       union {
+               float f;
+               Bit32u l;
+       }       blah;
+       blah.l = mem_readd(addr);
+       fpu.regs[store_to].d = static_cast<Real64>(blah.f);
+}
+
+static void FPU_FLD_F64(PhysPt addr,Bitu store_to) {
+       fpu.regs[store_to].l.lower = mem_readd(addr);
+       fpu.regs[store_to].l.upper = mem_readd(addr+4);
+}
+
+static void FPU_FLD_F80(PhysPt addr) {
+       fpu.regs[TOP].d = FPU_FLD80(addr);
+}
+
+static void FPU_FLD_I16(PhysPt addr,Bitu store_to) {
+       Bit16s blah = mem_readw(addr);
+       fpu.regs[store_to].d = static_cast<Real64>(blah);
+}
+
+static void FPU_FLD_I32(PhysPt addr,Bitu store_to) {
+       Bit32s blah = mem_readd(addr);
+       fpu.regs[store_to].d = static_cast<Real64>(blah);
+}
+
+static void FPU_FLD_I64(PhysPt addr,Bitu store_to) {
+       FPU_Reg blah;
+       blah.l.lower = mem_readd(addr);
+       blah.l.upper = mem_readd(addr+4);
+       fpu.regs[store_to].d = static_cast<Real64>(blah.ll);
+}
+
+static void FPU_FBLD(PhysPt addr,Bitu store_to) {
+       Bit64u val = 0;
+       Bitu in = 0;
+       Bit64u base = 1;
+       for(Bitu i = 0;i < 9;i++){
+               in = mem_readb(addr + i);
+               val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9
+               base *= 10;
+               val += ((( in>>4)&0xf) * base);
+               base *= 10;
+       }
+
+       //last number, only now convert to float in order to get
+       //the best signification
+       Real64 temp = static_cast<Real64>(val);
+       in = mem_readb(addr + 9);
+       temp += ( (in&0xf) * base );
+       if(in&0x80) temp *= -1.0;
+       fpu.regs[store_to].d = temp;
+}
+
+
+static INLINE void FPU_FLD_F32_EA(PhysPt addr) {
+       FPU_FLD_F32(addr,8);
+}
+static INLINE void FPU_FLD_F64_EA(PhysPt addr) {
+       FPU_FLD_F64(addr,8);
+}
+static INLINE void FPU_FLD_I32_EA(PhysPt addr) {
+       FPU_FLD_I32(addr,8);
+}
+static INLINE void FPU_FLD_I16_EA(PhysPt addr) {
+       FPU_FLD_I16(addr,8);
+}
+
+
+static void FPU_FST_F32(PhysPt addr) {
+       union {
+               float f;
+               Bit32u l;
+       }       blah;
+       //should depend on rounding method
+       blah.f = static_cast<float>(fpu.regs[TOP].d);
+       mem_writed(addr,blah.l);
+}
+
+static void FPU_FST_F64(PhysPt addr) {
+       mem_writed(addr,fpu.regs[TOP].l.lower);
+       mem_writed(addr+4,fpu.regs[TOP].l.upper);
+}
+
+static void FPU_FST_F80(PhysPt addr) {
+       FPU_ST80(addr,TOP);
+}
+
+static void FPU_FST_I16(PhysPt addr) {
+       mem_writew(addr,static_cast<Bit16s>(FROUND(fpu.regs[TOP].d)));
+}
+
+static void FPU_FST_I32(PhysPt addr) {
+       mem_writed(addr,static_cast<Bit32s>(FROUND(fpu.regs[TOP].d)));
+}
+
+static void FPU_FST_I64(PhysPt addr) {
+       FPU_Reg blah;
+       blah.ll = static_cast<Bit64s>(FROUND(fpu.regs[TOP].d));
+       mem_writed(addr,blah.l.lower);
+       mem_writed(addr+4,blah.l.upper);
+}
+
+static void FPU_FBST(PhysPt addr) {
+       FPU_Reg val = fpu.regs[TOP];
+       bool sign = false;
+       if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000)) { //sign
+               sign=true;
+               val.d=-val.d;
+       }
+       //numbers from back to front
+       Real64 temp=val.d;
+       Bitu p;
+       for(Bitu i=0;i<9;i++){
+               val.d=temp;
+               temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
+               p = static_cast<Bitu>(val.d - 10.0*temp);  
+               val.d=temp;
+               temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
+               p |= (static_cast<Bitu>(val.d - 10.0*temp)<<4);
+
+               mem_writeb(addr+i,p);
+       }
+       val.d=temp;
+       temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
+       p = static_cast<Bitu>(val.d - 10.0*temp);
+       if(sign)
+               p|=0x80;
+       mem_writeb(addr+9,p);
+}
+
+static void FPU_FADD(Bitu op1, Bitu op2){
+       fpu.regs[op1].d+=fpu.regs[op2].d;
+       //flags and such :)
+       return;
+}
+
+static void FPU_FSIN(void){
+       fpu.regs[TOP].d = sin(fpu.regs[TOP].d);
+       FPU_SET_C2(0);
+       //flags and such :)
+       return;
+}
+
+static void FPU_FSINCOS(void){
+       Real64 temp = fpu.regs[TOP].d;
+       fpu.regs[TOP].d = sin(temp);
+       FPU_PUSH(cos(temp));
+       FPU_SET_C2(0);
+       //flags and such :)
+       return;
+}
+
+static void FPU_FCOS(void){
+       fpu.regs[TOP].d = cos(fpu.regs[TOP].d);
+       FPU_SET_C2(0);
+       //flags and such :)
+       return;
+}
+
+static void FPU_FSQRT(void){
+       fpu.regs[TOP].d = sqrt(fpu.regs[TOP].d);
+       //flags and such :)
+       return;
+}
+static void FPU_FPATAN(void){
+       fpu.regs[STV(1)].d = atan2(fpu.regs[STV(1)].d,fpu.regs[TOP].d);
+       FPU_FPOP();
+       //flags and such :)
+       return;
+}
+static void FPU_FPTAN(void){
+       fpu.regs[TOP].d = tan(fpu.regs[TOP].d);
+       FPU_PUSH(1.0);
+       FPU_SET_C2(0);
+       //flags and such :)
+       return;
+}
+static void FPU_FDIV(Bitu st, Bitu other){
+       fpu.regs[st].d= fpu.regs[st].d/fpu.regs[other].d;
+       //flags and such :)
+       return;
+}
+
+static void FPU_FDIVR(Bitu st, Bitu other){
+       fpu.regs[st].d= fpu.regs[other].d/fpu.regs[st].d;
+       // flags and such :)
+       return;
+}
+
+static void FPU_FMUL(Bitu st, Bitu other){
+       fpu.regs[st].d*=fpu.regs[other].d;
+       //flags and such :)
+       return;
+}
+
+static void FPU_FSUB(Bitu st, Bitu other){
+       fpu.regs[st].d = fpu.regs[st].d - fpu.regs[other].d;
+       //flags and such :)
+       return;
+}
+
+static void FPU_FSUBR(Bitu st, Bitu other){
+       fpu.regs[st].d= fpu.regs[other].d - fpu.regs[st].d;
+       //flags and such :)
+       return;
+}
+
+static void FPU_FXCH(Bitu st, Bitu other){
+       FPU_Tag tag = fpu.tags[other];
+       FPU_Reg reg = fpu.regs[other];
+       fpu.tags[other] = fpu.tags[st];
+       fpu.regs[other] = fpu.regs[st];
+       fpu.tags[st] = tag;
+       fpu.regs[st] = reg;
+}
+
+static void FPU_FST(Bitu st, Bitu other){
+       fpu.tags[other] = fpu.tags[st];
+       fpu.regs[other] = fpu.regs[st];
+}
+
+
+static void FPU_FCOM(Bitu st, Bitu other){
+       if(((fpu.tags[st] != TAG_Valid) && (fpu.tags[st] != TAG_Zero)) || 
+               ((fpu.tags[other] != TAG_Valid) && (fpu.tags[other] != TAG_Zero))){
+               FPU_SET_C3(1);FPU_SET_C2(1);FPU_SET_C0(1);return;
+       }
+       if(fpu.regs[st].d == fpu.regs[other].d){
+               FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);return;
+       }
+       if(fpu.regs[st].d < fpu.regs[other].d){
+               FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(1);return;
+       }
+       // st > other
+       FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(0);return;
+}
+
+static void FPU_FUCOM(Bitu st, Bitu other){
+       //does atm the same as fcom 
+       FPU_FCOM(st,other);
+}
+
+static void FPU_FRNDINT(void){
+       Bit64s temp= static_cast<Bit64s>(FROUND(fpu.regs[TOP].d));
+       fpu.regs[TOP].d=static_cast<double>(temp);
+}
+
+static void FPU_FPREM(void){
+       Real64 valtop = fpu.regs[TOP].d;
+       Real64 valdiv = fpu.regs[STV(1)].d;
+       Bit64s ressaved = static_cast<Bit64s>( (valtop/valdiv) );
+// Some backups
+//     Real64 res=valtop - ressaved*valdiv; 
+//      res= fmod(valtop,valdiv);
+       fpu.regs[TOP].d = valtop - ressaved*valdiv;
+       FPU_SET_C0(static_cast<Bitu>(ressaved&4));
+       FPU_SET_C3(static_cast<Bitu>(ressaved&2));
+       FPU_SET_C1(static_cast<Bitu>(ressaved&1));
+       FPU_SET_C2(0);
+}
+
+static void FPU_FPREM1(void){
+       Real64 valtop = fpu.regs[TOP].d;
+       Real64 valdiv = fpu.regs[STV(1)].d;
+       double quot = valtop/valdiv;
+       double quotf = floor(quot);
+       Bit64s ressaved;
+       if (quot-quotf>0.5) ressaved = static_cast<Bit64s>(quotf+1);
+       else if (quot-quotf<0.5) ressaved = static_cast<Bit64s>(quotf);
+       else ressaved = static_cast<Bit64s>((((static_cast<Bit64s>(quotf))&1)!=0)?(quotf+1):(quotf));
+       fpu.regs[TOP].d = valtop - ressaved*valdiv;
+       FPU_SET_C0(static_cast<Bitu>(ressaved&4));
+       FPU_SET_C3(static_cast<Bitu>(ressaved&2));
+       FPU_SET_C1(static_cast<Bitu>(ressaved&1));
+       FPU_SET_C2(0);
+}
+
+static void FPU_FXAM(void){
+       if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000))     //sign
+       { 
+               FPU_SET_C1(1);
+       } 
+       else 
+       {
+               FPU_SET_C1(0);
+       }
+       if(fpu.tags[TOP] == TAG_Empty)
+       {
+               FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1);
+               return;
+       }
+       if(fpu.regs[TOP].d == 0.0)              //zero or normalized number.
+       { 
+               FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);
+       }
+       else
+       {
+               FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0);
+       }
+}
+
+
+static void FPU_F2XM1(void){
+       fpu.regs[TOP].d = pow(2.0,fpu.regs[TOP].d) - 1;
+       return;
+}
+
+static void FPU_FYL2X(void){
+       fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d)/log(static_cast<Real64>(2.0));
+       FPU_FPOP();
+       return;
+}
+
+static void FPU_FYL2XP1(void){
+       fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d+1.0)/log(static_cast<Real64>(2.0));
+       FPU_FPOP();
+       return;
+}
+
+static void FPU_FSCALE(void){
+       fpu.regs[TOP].d *= pow(2.0,static_cast<Real64>(static_cast<Bit64s>(fpu.regs[STV(1)].d)));
+       return; //2^x where x is chopped.
+}
+
+static void FPU_FSTENV(PhysPt addr){
+       FPU_SET_TOP(TOP);
+       if(!cpu.code.big) {
+               mem_writew(addr+0,static_cast<Bit16u>(fpu.cw));
+               mem_writew(addr+2,static_cast<Bit16u>(fpu.sw));
+               mem_writew(addr+4,static_cast<Bit16u>(FPU_GetTag()));
+       } else { 
+               mem_writed(addr+0,static_cast<Bit32u>(fpu.cw));
+               mem_writed(addr+4,static_cast<Bit32u>(fpu.sw));
+               mem_writed(addr+8,static_cast<Bit32u>(FPU_GetTag()));
+       }
+}
+
+static void FPU_FLDENV(PhysPt addr){
+       Bit16u tag;
+       Bit32u tagbig;
+       Bitu cw;
+       if(!cpu.code.big) {
+               cw     = mem_readw(addr+0);
+               fpu.sw = mem_readw(addr+2);
+               tag    = mem_readw(addr+4);
+       } else { 
+               cw     = mem_readd(addr+0);
+               fpu.sw = (Bit16u)mem_readd(addr+4);
+               tagbig = mem_readd(addr+8);
+               tag    = static_cast<Bit16u>(tagbig);
+       }
+       FPU_SetTag(tag);
+       FPU_SetCW(cw);
+       TOP = FPU_GET_TOP();
+}
+
+static void FPU_FSAVE(PhysPt addr){
+       FPU_FSTENV(addr);
+       Bitu start = (cpu.code.big?28:14);
+       for(Bitu i = 0;i < 8;i++){
+               FPU_ST80(addr+start,STV(i));
+               start += 10;
+       }
+       FPU_FINIT();
+}
+
+static void FPU_FRSTOR(PhysPt addr){
+       FPU_FLDENV(addr);
+       Bitu start = (cpu.code.big?28:14);
+       for(Bitu i = 0;i < 8;i++){
+               fpu.regs[STV(i)].d = FPU_FLD80(addr+start);
+               start += 10;
+       }
+}
+
+static void FPU_FXTRACT(void) {
+       // function stores real bias in st and 
+       // pushes the significant number onto the stack
+       // if double ever uses a different base please correct this function
+
+       FPU_Reg test = fpu.regs[TOP];
+       Bit64s exp80 =  test.ll&LONGTYPE(0x7ff0000000000000);
+       Bit64s exp80final = (exp80>>52) - BIAS64;
+       Real64 mant = test.d / (pow(2.0,static_cast<Real64>(exp80final)));
+       fpu.regs[TOP].d = static_cast<Real64>(exp80final);
+       FPU_PUSH(mant);
+}
+
+static void FPU_FCHS(void){
+       fpu.regs[TOP].d = -1.0*(fpu.regs[TOP].d);
+}
+
+static void FPU_FABS(void){
+       fpu.regs[TOP].d = fabs(fpu.regs[TOP].d);
+}
+
+static void FPU_FTST(void){
+       fpu.regs[8].d = 0.0;
+       FPU_FCOM(TOP,8);
+}
+
+static void FPU_FLD1(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = 1.0;
+}
+
+static void FPU_FLDL2T(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = L2T;
+}
+
+static void FPU_FLDL2E(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = L2E;
+}
+
+static void FPU_FLDPI(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = PI;
+}
+
+static void FPU_FLDLG2(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = LG2;
+}
+
+static void FPU_FLDLN2(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = LN2;
+}
+
+static void FPU_FLDZ(void){
+       FPU_PREP_PUSH();
+       fpu.regs[TOP].d = 0.0;
+       fpu.tags[TOP] = TAG_Zero;
+}
+
+
+static INLINE void FPU_FADD_EA(Bitu op1){
+       FPU_FADD(op1,8);
+}
+static INLINE void FPU_FMUL_EA(Bitu op1){
+       FPU_FMUL(op1,8);
+}
+static INLINE void FPU_FSUB_EA(Bitu op1){
+       FPU_FSUB(op1,8);
+}
+static INLINE void FPU_FSUBR_EA(Bitu op1){
+       FPU_FSUBR(op1,8);
+}
+static INLINE void FPU_FDIV_EA(Bitu op1){
+       FPU_FDIV(op1,8);
+}
+static INLINE void FPU_FDIVR_EA(Bitu op1){
+       FPU_FDIVR(op1,8);
+}
+static INLINE void FPU_FCOM_EA(Bitu op1){
+       FPU_FCOM(op1,8);
+}
+
diff --git a/dosbox/fpu_instructions_x86.h b/dosbox/fpu_instructions_x86.h
new file mode 100644 (file)
index 0000000..16d96d6
--- /dev/null
@@ -0,0 +1,1489 @@
+/*
+ *  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: fpu_instructions_x86.h,v 1.7 2009-05-27 09:15:41 qbix79 Exp $ */
+
+
+// #define WEAK_EXCEPTIONS
+
+
+#if defined (_MSC_VER)
+
+#ifdef WEAK_EXCEPTIONS
+#define clx
+#else
+#define clx fclex
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_LOAD(op,szI,szA)                  \
+               __asm {                                                 \
+               __asm   mov             ebx, store_to   \
+               __asm   shl             ebx, 4                  \
+               __asm   op              szI PTR fpu.p_regs[128].m1              \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }
+#else
+#define FPUD_LOAD(op,szI,szA)                  \
+               Bit16u new_sw;                                  \
+               __asm {                                                 \
+               __asm   mov             eax, 8                  \
+               __asm   shl             eax, 4                  \
+               __asm   mov             ebx, store_to   \
+               __asm   shl             ebx, 4                  \
+               __asm   fclex                                   \
+               __asm   op              szI PTR fpu.p_regs[eax].m1              \
+               __asm   fnstsw  new_sw                  \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }                                                               \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_LOAD_EA(op,szI,szA)               \
+               __asm {                                                 \
+               __asm   op              szI PTR fpu.p_regs[128].m1              \
+               }
+#else
+#define FPUD_LOAD_EA(op,szI,szA)               \
+               Bit16u new_sw;                                  \
+               __asm {                                                 \
+               __asm   mov             eax, 8                  \
+               __asm   shl             eax, 4                  \
+               __asm   fclex                                   \
+               __asm   op              szI PTR fpu.p_regs[eax].m1              \
+               __asm   fnstsw  new_sw                  \
+               }                                                               \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_STORE(op,szI,szA)                         \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, TOP                        \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   op              szI PTR fpu.p_regs[128].m1              \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_STORE(op,szI,szA)                         \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             eax, TOP                        \
+               __asm   shl             eax, 4                          \
+               __asm   mov             ebx, 8                          \
+               __asm   shl             ebx, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                                     \
+               __asm   op              szI PTR fpu.p_regs[ebx].m1              \
+               __asm   fnstsw  new_sw                          \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fsin,fcos,f2xm1,fchs,fabs
+#define FPUD_TRIG(op)                          \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                     \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               }                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fsincos
+#define FPUD_SINCOS()                          \
+               Bit16u new_sw;                                  \
+               __asm {                                                 \
+               __asm   mov             eax, TOP                \
+               __asm   mov             ebx, eax                \
+               __asm   dec     ebx                             \
+               __asm   and     ebx, 7                  \
+               __asm   shl             eax, 4                  \
+               __asm   shl             ebx, 4                  \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                             \
+               __asm   fsincos                                 \
+               __asm   fnstsw  new_sw                  \
+               __asm   mov             cx, new_sw              \
+               __asm   and             ch, 0x04                \
+               __asm   jnz             argument_too_large1                             \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   jmp             end_sincos              \
+               __asm   argument_too_large1:    \
+               __asm   fstp    st(0)                   \
+               __asm   end_sincos:                             \
+               }                                                                                               \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);               \
+               if ((new_sw&0x0400)==0) FPU_PREP_PUSH();
+
+// handles fptan
+#define FPUD_PTAN()                                    \
+               Bit16u new_sw;                                  \
+               __asm {                                                 \
+               __asm   mov             eax, TOP                \
+               __asm   mov             ebx, eax                \
+               __asm   dec     ebx                             \
+               __asm   and     ebx, 7                  \
+               __asm   shl             eax, 4                  \
+               __asm   shl             ebx, 4                  \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                     \
+               __asm   fptan                                   \
+               __asm   fnstsw  new_sw                  \
+               __asm   mov             cx, new_sw              \
+               __asm   and             ch, 0x04                \
+               __asm   jnz             argument_too_large2                             \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   jmp             end_ptan                \
+               __asm   argument_too_large2:    \
+               __asm   fstp    st(0)                   \
+               __asm   end_ptan:                               \
+               }                                                                                               \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);               \
+               if ((new_sw&0x0400)==0) FPU_PREP_PUSH();
+
+// handles fxtract
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_XTRACT                                            \
+               __asm {                                                 \
+               __asm   mov             eax, TOP                \
+               __asm   mov             ebx, eax                \
+               __asm   dec     ebx                             \
+               __asm   and     ebx, 7                  \
+               __asm   shl             eax, 4                  \
+               __asm   shl             ebx, 4                  \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fxtract                                 \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               }                                                                                               \
+               FPU_PREP_PUSH();
+#else
+#define FPUD_XTRACT                                            \
+               Bit16u new_sw;                                  \
+               __asm {                                                 \
+               __asm   mov             eax, TOP                \
+               __asm   mov             ebx, eax                \
+               __asm   dec     ebx                             \
+               __asm   and     ebx, 7                  \
+               __asm   shl             eax, 4                  \
+               __asm   shl             ebx, 4                  \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fclex                                   \
+               __asm   fxtract                                 \
+               __asm   fnstsw  new_sw                  \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               }                                                                                               \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);                 \
+               FPU_PREP_PUSH();
+#endif
+
+// handles fadd,fmul,fsub,fsubr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH1(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, op1                        \
+               __asm   shl             eax, 4                          \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             ebx, op2                        \
+               __asm   shl             ebx, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   op              st(1), st(0)            \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_ARITH1(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             eax, op1                        \
+               __asm   shl             eax, 4                          \
+               __asm   mov             ebx, op2                        \
+               __asm   shl             ebx, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   clx                                                     \
+               __asm   op              st(1), st(0)            \
+               __asm   fnstsw  new_sw                          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fadd,fmul,fsub,fsubr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH1_EA(op)                                     \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, op1                        \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fxch    \
+               __asm   op              st(1), st(0)            \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_ARITH1_EA(op)                                     \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             eax, op1                        \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fxch    \
+               __asm   clx                                                     \
+               __asm   op              st(1), st(0)            \
+               __asm   fnstsw  new_sw                          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fsqrt,frndint
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH2(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, TOP                        \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   op                                                      \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_ARITH2(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             eax, TOP                        \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                                     \
+               __asm   op                                                      \
+               __asm   fnstsw  new_sw                          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fdiv,fdivr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH3(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, op1                        \
+               __asm   shl             eax, 4                          \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             ebx, op2                        \
+               __asm   shl             ebx, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   op              st(1), st(0)            \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_ARITH3(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   mov             eax, op1                        \
+               __asm   shl             eax, 4                          \
+               __asm   mov             ebx, op2                        \
+               __asm   shl             ebx, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fclex                                           \
+               __asm   op              st(1), st(0)            \
+               __asm   fnstsw  new_sw                          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+// handles fdiv,fdivr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH3_EA(op)                                     \
+               Bit16u save_cw;                                         \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, op1                        \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fxch    \
+               __asm   op              st(1), st(0)            \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }
+#else
+#define FPUD_ARITH3_EA(op)                                     \
+               Bit16u new_sw,save_cw;                          \
+               __asm {                                                         \
+               __asm   fnstcw  save_cw                         \
+               __asm   mov             eax, op1                        \
+               __asm   fldcw   fpu.cw_mask_all         \
+               __asm   shl             eax, 4                          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fxch    \
+               __asm   fclex                                           \
+               __asm   op              st(1), st(0)            \
+               __asm   fnstsw  new_sw                          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1     \
+               __asm   fldcw   save_cw                         \
+               }                                                                       \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+// handles fprem,fprem1,fscale
+#define FPUD_REMINDER(op)                      \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   mov             ebx, eax        \
+               __asm   inc     ebx                     \
+               __asm   and     ebx, 7          \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fclex                           \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fstp    st(0)           \
+               }                                                       \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+
+// handles fcom,fucom
+#define FPUD_COMPARE(op)                       \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             ebx, op2        \
+               __asm   mov             eax, op1        \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                     \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               }                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+#define FPUD_COMPARE_EA(op)                    \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, op1        \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                     \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               }                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fxam,ftst
+#define FPUD_EXAMINE(op)                       \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   clx                                     \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               __asm   fstp    st(0)           \
+               }                                                       \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fpatan,fyl2xp1
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_WITH_POP(op)                      \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   mov             ebx, eax        \
+               __asm   inc     ebx                     \
+               __asm   and     ebx, 7          \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   op                                      \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }                                                       \
+               FPU_FPOP();
+#else
+#define FPUD_WITH_POP(op)                      \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   mov             ebx, eax        \
+               __asm   inc     ebx                     \
+               __asm   and     ebx, 7          \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fclex                           \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }                                                               \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \
+               FPU_FPOP();
+#endif
+
+// handles fyl2x
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_FYL2X(op)                         \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   mov             ebx, eax        \
+               __asm   inc     ebx                     \
+               __asm   and     ebx, 7          \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   op                                      \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }                                                               \
+               FPU_FPOP();
+#else
+#define FPUD_FYL2X(op)                         \
+               Bit16u new_sw;                          \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   mov             ebx, eax        \
+               __asm   inc     ebx                     \
+               __asm   and     ebx, 7          \
+               __asm   shl             ebx, 4          \
+               __asm   shl             eax, 4          \
+               __asm   fld             TBYTE PTR fpu.p_regs[ebx].m1    \
+               __asm   fld             TBYTE PTR fpu.p_regs[eax].m1    \
+               __asm   fclex                           \
+               __asm   op                                      \
+               __asm   fnstsw  new_sw          \
+               __asm   fstp    TBYTE PTR fpu.p_regs[ebx].m1    \
+               }                                                               \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \
+               FPU_FPOP();
+#endif
+
+// load math constants
+#define FPUD_LOAD_CONST(op)            \
+               FPU_PREP_PUSH();                        \
+               __asm {                                         \
+               __asm   mov             eax, TOP        \
+               __asm   shl             eax, 4          \
+               __asm   clx                                     \
+               __asm   op                                      \
+               __asm   fstp    TBYTE PTR fpu.p_regs[eax].m1    \
+               }                                                       \
+
+#else
+
+#ifdef WEAK_EXCEPTIONS
+#define clx
+#else
+#define clx "fclex"
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_LOAD(op,szI,szA)                          \
+               __asm__ volatile (                                      \
+                       "movl           $128, %%eax             \n"     \
+                       "shl            $4, %0                  \n"     \
+                       #op #szA "      (%1, %%eax)             \n"     \
+                       "fstpt          (%1, %0)                "       \
+                       :                                                               \
+                       :       "r" (store_to), "r" (fpu.p_regs)        \
+                       :       "eax", "memory"                                         \
+               );
+#else
+#define FPUD_LOAD(op,szI,szA)                          \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           $8, %%eax               \n"     \
+                       "shl            $4, %%eax               \n"     \
+                       "shl            $4, %1                  \n"     \
+                       "fclex                                          \n"     \
+                       #op #szA "      (%2, %%eax)             \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %1)                "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (store_to), "r" (fpu.p_regs)        \
+                       :       "eax", "memory"                                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_LOAD_EA(op,szI,szA)                       \
+               __asm__ volatile (                                      \
+                       "movl           $128, %%eax             \n"     \
+                       #op #szA "      (%0, %%eax)             \n"     \
+                       :                                                               \
+                       :       "r" (fpu.p_regs)                        \
+                       :       "eax", "memory"                         \
+               );
+#else
+#define FPUD_LOAD_EA(op,szI,szA)                       \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           $8, %%eax               \n"     \
+                       "shl            $4, %%eax               \n"     \
+                       "fclex                                          \n"     \
+                       #op #szA "      (%1, %%eax)             \n"     \
+                       "fnstsw         %0                              \n"     \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (fpu.p_regs)                        \
+                       :       "eax", "memory"                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_STORE(op,szI,szA)                         \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldcw          %3                              \n"     \
+                       "movl           $128, %%eax             \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       #op #szA "      (%2, %%eax)             \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)                          \
+                       :       "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "eax", "memory"                                         \
+               );
+#else
+#define FPUD_STORE(op,szI,szA)                         \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "movl           $8, %%eax               \n"     \
+                       "shl            $4, %%eax               \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       clx"                                            \n"     \
+                       #op #szA "      (%3, %%eax)             \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)   \
+                       :       "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "eax", "memory"                                         \
+               );                                                                              \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fsin,fcos,f2xm1,fchs,fabs
+#define FPUD_TRIG(op)                                          \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %1)                "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "memory"                                        \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fsincos
+#define FPUD_SINCOS()                                  \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "decl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       clx"                                            \n"     \
+                       "fsincos                                        \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %%eax)             \n"     \
+                       "movw           %0, %%ax                \n"     \
+                       "sahf                                           \n"     \
+                       "jp                     argument_too_large1             \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "argument_too_large1:           "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "cc", "memory"           \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);               \
+               if ((new_sw&0x0400)==0) FPU_PREP_PUSH();
+
+// handles fptan
+#define FPUD_PTAN()                                            \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "decl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       clx"                                            \n"     \
+                       "fptan                                          \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %%eax)             \n"     \
+                       "movw           %0, %%ax                \n"     \
+                       "sahf                                           \n"     \
+                       "jp                     argument_too_large2             \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "argument_too_large2:           "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "cc", "memory"           \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);               \
+               if ((new_sw&0x0400)==0) FPU_PREP_PUSH();
+
+// handles fxtract
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_XTRACT                                            \
+               __asm__ volatile (                                      \
+                       "movl           %0, %%eax               \n"     \
+                       "shll           $4, %0                  \n"     \
+                       "decl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "fldt           (%1, %0)                \n"     \
+                       "fxtract                                        \n"     \
+                       "fstpt          (%1, %%eax)             \n"     \
+                       "fstpt          (%1, %0)                "       \
+                       :                                                               \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                         \
+               );                                                                      \
+               FPU_PREP_PUSH();
+#else
+#define FPUD_XTRACT                                            \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "decl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       "fclex                                          \n"     \
+                       "fxtract                                        \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %%eax)             \n"     \
+                       "fstpt          (%2, %1)                "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);         \
+               FPU_PREP_PUSH();
+#endif
+
+// handles fadd,fmul,fsub,fsubr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH1(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       "fldt           (%3, %1)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%3, %1)                \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)          \
+                       :       "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)           \
+                       :       "memory"                                \
+               );
+#else
+#define FPUD_ARITH1(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %5                              \n"     \
+                       "shll           $4, %3                  \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "fldt           (%4, %3)                \n"     \
+                       "fldt           (%4, %2)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%4, %2)                \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)           \
+                       :       "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)           \
+                       :       "memory"                                \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fadd,fmul,fsub,fsubr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH1_EA(op)                                     \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "fldcw          %3                              \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)          \
+                       :       "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                \
+               );
+#else
+#define FPUD_ARITH1_EA(op)                                     \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%3, %2)                \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)           \
+                       :       "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fsqrt,frndint
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH2(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "fldcw          %3                              \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)                          \
+                       :       "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                \
+               );
+#else
+#define FPUD_ARITH2(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%3, %2)                \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)   \
+                       :       "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                \
+               );                                                                              \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+#endif
+
+// handles fdiv,fdivr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH3(op)                                                \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       "fldt           (%3, %1)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%3, %1)                \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)                          \
+                       :       "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)           \
+                       :       "memory"                                        \
+               );
+#else
+#define FPUD_ARITH3(op)                                                \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %5                              \n"     \
+                       "shll           $4, %3                  \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "fldt           (%4, %3)                \n"     \
+                       "fldt           (%4, %2)                \n"     \
+                       "fclex                                          \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%4, %2)                \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)           \
+                       :       "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)           \
+                       :       "memory"                                        \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+// handles fdiv,fdivr
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_ARITH3_EA(op)                                     \
+               Bit16u save_cw;                                         \
+               __asm__ volatile (                                      \
+                       "fnstcw         %0                              \n"     \
+                       "fldcw          %3                              \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "fldcw          %0                              "       \
+                       :       "=m" (save_cw)                          \
+                       :       "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                        \
+               );
+#else
+#define FPUD_ARITH3_EA(op)                                     \
+               Bit16u new_sw,save_cw;                          \
+               __asm__ volatile (                                      \
+                       "fnstcw         %1                              \n"     \
+                       "fldcw          %4                              \n"     \
+                       "shll           $4, %2                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       "fclex                                          \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%3, %2)                \n"     \
+                       "fldcw          %1                              "       \
+                       :       "=m" (new_sw), "=m" (save_cw)           \
+                       :       "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all)              \
+                       :       "memory"                                        \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+#endif
+
+// handles fprem,fprem1,fscale
+#define FPUD_REMINDER(op)                                      \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "incl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %%eax)             \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       "fclex                                          \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %1)                \n"     \
+                       "fstp           %%st(0)                 "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);
+
+// handles fcom,fucom
+#define FPUD_COMPARE(op)                                       \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "shll           $4, %2                  \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%3, %2)                \n"     \
+                       "fldt           (%3, %1)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (op1), "r" (op2), "r" (fpu.p_regs)          \
+                       :       "memory"                                        \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fcom,fucom
+#define FPUD_COMPARE_EA(op)                                    \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (op1), "r" (fpu.p_regs)             \
+                       :       "memory"                                        \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fxam,ftst
+#define FPUD_EXAMINE(op)                                       \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstp           %%st(0)                 "       \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "memory"                                \
+               );                                                                      \
+               fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff);
+
+// handles fpatan,fyl2xp1
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_WITH_POP(op)                                      \
+               __asm__ volatile (                                      \
+                       "movl           %0, %%eax               \n"     \
+                       "incl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "shll           $4, %0                  \n"     \
+                       "fldt           (%1, %%eax)             \n"     \
+                       "fldt           (%1, %0)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%1, %%eax)             \n"     \
+                       :                                                               \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                         \
+               );                                                                      \
+               FPU_FPOP();
+#else
+#define FPUD_WITH_POP(op)                                      \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "incl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %%eax)             \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       "fclex                                          \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %%eax)             \n"     \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);         \
+               FPU_FPOP();
+#endif
+
+// handles fyl2x
+#ifdef WEAK_EXCEPTIONS
+#define FPUD_FYL2X(op)                                         \
+               __asm__ volatile (                                      \
+                       "movl           %0, %%eax               \n"     \
+                       "incl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "shll           $4, %0                  \n"     \
+                       "fldt           (%1, %%eax)             \n"     \
+                       "fldt           (%1, %0)                \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%1, %%eax)             \n"     \
+                       :                                                               \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                         \
+               );                                                                      \
+               FPU_FPOP();
+#else
+#define FPUD_FYL2X(op)                                         \
+               Bit16u new_sw;                                          \
+               __asm__ volatile (                                      \
+                       "movl           %1, %%eax               \n"     \
+                       "incl           %%eax                   \n"     \
+                       "andl           $7, %%eax               \n"     \
+                       "shll           $4, %%eax               \n"     \
+                       "shll           $4, %1                  \n"     \
+                       "fldt           (%2, %%eax)             \n"     \
+                       "fldt           (%2, %1)                \n"     \
+                       "fclex                                          \n"     \
+                       #op"                                            \n"     \
+                       "fnstsw         %0                              \n"     \
+                       "fstpt          (%2, %%eax)             \n"     \
+                       :       "=m" (new_sw)                           \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "eax", "memory"                         \
+               );                                                                      \
+               fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff);         \
+               FPU_FPOP();
+#endif
+
+// load math constants
+#define FPUD_LOAD_CONST(op)                            \
+               FPU_PREP_PUSH();                                        \
+               __asm__ volatile (                                      \
+                       "shll           $4, %0                  \n"     \
+                       clx"                                            \n"     \
+                       #op"                                            \n"     \
+                       "fstpt          (%1, %0)                \n"     \
+                       :                                                               \
+                       :       "r" (TOP), "r" (fpu.p_regs)     \
+                       :       "memory"                                        \
+               );
+
+#endif
+
+#ifdef WEAK_EXCEPTIONS
+const Bit16u exc_mask=0x7f00;
+#else
+const Bit16u exc_mask=0xffbf;
+#endif
+
+static void FPU_FINIT(void) {
+       FPU_SetCW(0x37F);
+       fpu.sw=0;
+       TOP=FPU_GET_TOP();
+       fpu.tags[0]=TAG_Empty;
+       fpu.tags[1]=TAG_Empty;
+       fpu.tags[2]=TAG_Empty;
+       fpu.tags[3]=TAG_Empty;
+       fpu.tags[4]=TAG_Empty;
+       fpu.tags[5]=TAG_Empty;
+       fpu.tags[6]=TAG_Empty;
+       fpu.tags[7]=TAG_Empty;
+       fpu.tags[8]=TAG_Valid; // is only used by us
+}
+
+static void FPU_FCLEX(void){
+       fpu.sw&=0x7f00;                         //should clear exceptions
+}
+
+static void FPU_FNOP(void){
+}
+
+static void FPU_PREP_PUSH(void){
+       TOP = (TOP - 1) &7;
+       fpu.tags[TOP]=TAG_Valid;
+}
+
+static void FPU_FPOP(void){
+       fpu.tags[TOP]=TAG_Empty;
+       TOP = ((TOP+1)&7);
+}
+
+static void FPU_FLD_F32(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       FPUD_LOAD(fld,DWORD,s)
+}
+
+static void FPU_FLD_F32_EA(PhysPt addr) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       FPUD_LOAD_EA(fld,DWORD,s)
+}
+
+static void FPU_FLD_F64(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       fpu.p_regs[8].m2 = mem_readd(addr+4);
+       FPUD_LOAD(fld,QWORD,l)
+}
+
+static void FPU_FLD_F64_EA(PhysPt addr) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       fpu.p_regs[8].m2 = mem_readd(addr+4);
+       FPUD_LOAD_EA(fld,QWORD,l)
+}
+
+static void FPU_FLD_F80(PhysPt addr) {
+       fpu.p_regs[TOP].m1 = mem_readd(addr);
+       fpu.p_regs[TOP].m2 = mem_readd(addr+4);
+       fpu.p_regs[TOP].m3 = mem_readw(addr+8);
+       FPU_SET_C1(0);
+}
+
+static void FPU_FLD_I16(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr);
+       FPUD_LOAD(fild,WORD,)
+}
+
+static void FPU_FLD_I16_EA(PhysPt addr) {
+       fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr);
+       FPUD_LOAD_EA(fild,WORD,)
+}
+
+static void FPU_FLD_I32(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       FPUD_LOAD(fild,DWORD,l)
+}
+
+static void FPU_FLD_I32_EA(PhysPt addr) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       FPUD_LOAD_EA(fild,DWORD,l)
+}
+
+static void FPU_FLD_I64(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       fpu.p_regs[8].m2 = mem_readd(addr+4);
+       FPUD_LOAD(fild,QWORD,q)
+}
+
+static void FPU_FBLD(PhysPt addr,Bitu store_to) {
+       fpu.p_regs[8].m1 = mem_readd(addr);
+       fpu.p_regs[8].m2 = mem_readd(addr+4);
+       fpu.p_regs[8].m3 = mem_readw(addr+8);
+       FPUD_LOAD(fbld,TBYTE,)
+}
+
+static void FPU_FST_F32(PhysPt addr) {
+       FPUD_STORE(fstp,DWORD,s)
+       mem_writed(addr,fpu.p_regs[8].m1);
+}
+
+static void FPU_FST_F64(PhysPt addr) {
+       FPUD_STORE(fstp,QWORD,l)
+       mem_writed(addr,fpu.p_regs[8].m1);
+       mem_writed(addr+4,fpu.p_regs[8].m2);
+}
+
+static void FPU_FST_F80(PhysPt addr) {
+       mem_writed(addr,fpu.p_regs[TOP].m1);
+       mem_writed(addr+4,fpu.p_regs[TOP].m2);
+       mem_writew(addr+8,fpu.p_regs[TOP].m3);
+       FPU_SET_C1(0);
+}
+
+static void FPU_FST_I16(PhysPt addr) {
+       FPUD_STORE(fistp,WORD,)
+       mem_writew(addr,(Bit16u)fpu.p_regs[8].m1);
+}
+
+static void FPU_FST_I32(PhysPt addr) {
+       FPUD_STORE(fistp,DWORD,l)
+       mem_writed(addr,fpu.p_regs[8].m1);
+}
+
+static void FPU_FST_I64(PhysPt addr) {
+       FPUD_STORE(fistp,QWORD,q)
+       mem_writed(addr,fpu.p_regs[8].m1);
+       mem_writed(addr+4,fpu.p_regs[8].m2);
+}
+
+static void FPU_FBST(PhysPt addr) {
+       FPUD_STORE(fbstp,TBYTE,)
+       mem_writed(addr,fpu.p_regs[8].m1);
+       mem_writed(addr+4,fpu.p_regs[8].m2);
+       mem_writew(addr+8,fpu.p_regs[8].m3);
+}
+
+
+static void FPU_FSIN(void){
+       FPUD_TRIG(fsin)
+}
+
+static void FPU_FSINCOS(void){
+       FPUD_SINCOS()
+}
+
+static void FPU_FCOS(void){
+       FPUD_TRIG(fcos)
+}
+
+static void FPU_FSQRT(void){
+       FPUD_ARITH2(fsqrt)
+}
+
+static void FPU_FPATAN(void){
+       FPUD_WITH_POP(fpatan)
+}
+
+static void FPU_FPTAN(void){
+       FPUD_PTAN()
+}
+
+
+static void FPU_FADD(Bitu op1, Bitu op2){
+       FPUD_ARITH1(faddp)
+}
+
+static void FPU_FADD_EA(Bitu op1){
+       FPUD_ARITH1_EA(faddp)
+}
+
+static void FPU_FDIV(Bitu op1, Bitu op2){
+       FPUD_ARITH3(fdivp)
+}
+
+static void FPU_FDIV_EA(Bitu op1){
+       FPUD_ARITH3_EA(fdivp)
+}
+
+static void FPU_FDIVR(Bitu op1, Bitu op2){
+       FPUD_ARITH3(fdivrp)
+}
+
+static void FPU_FDIVR_EA(Bitu op1){
+       FPUD_ARITH3_EA(fdivrp)
+}
+
+static void FPU_FMUL(Bitu op1, Bitu op2){
+       FPUD_ARITH1(fmulp)
+}
+
+static void FPU_FMUL_EA(Bitu op1){
+       FPUD_ARITH1_EA(fmulp)
+}
+
+static void FPU_FSUB(Bitu op1, Bitu op2){
+       FPUD_ARITH1(fsubp)
+}
+
+static void FPU_FSUB_EA(Bitu op1){
+       FPUD_ARITH1_EA(fsubp)
+}
+
+static void FPU_FSUBR(Bitu op1, Bitu op2){
+       FPUD_ARITH1(fsubrp)
+}
+
+static void FPU_FSUBR_EA(Bitu op1){
+       FPUD_ARITH1_EA(fsubrp)
+}
+
+static void FPU_FXCH(Bitu stv, Bitu other){
+       FPU_Tag tag = fpu.tags[other];
+       fpu.tags[other] = fpu.tags[stv];
+       fpu.tags[stv] = tag;
+
+       Bit32u m1s = fpu.p_regs[other].m1;
+       Bit32u m2s = fpu.p_regs[other].m2;
+       Bit16u m3s = fpu.p_regs[other].m3;
+       fpu.p_regs[other].m1 = fpu.p_regs[stv].m1;
+       fpu.p_regs[other].m2 = fpu.p_regs[stv].m2;
+       fpu.p_regs[other].m3 = fpu.p_regs[stv].m3;
+       fpu.p_regs[stv].m1 = m1s;
+       fpu.p_regs[stv].m2 = m2s;
+       fpu.p_regs[stv].m3 = m3s;
+
+       FPU_SET_C1(0);
+}
+
+static void FPU_FST(Bitu stv, Bitu other){
+       fpu.tags[other] = fpu.tags[stv];
+
+       fpu.p_regs[other].m1 = fpu.p_regs[stv].m1;
+       fpu.p_regs[other].m2 = fpu.p_regs[stv].m2;
+       fpu.p_regs[other].m3 = fpu.p_regs[stv].m3;
+
+       FPU_SET_C1(0);
+}
+
+
+static void FPU_FCOM(Bitu op1, Bitu op2){
+       FPUD_COMPARE(fcompp)
+}
+
+static void FPU_FCOM_EA(Bitu op1){
+       FPUD_COMPARE_EA(fcompp)
+}
+
+static void FPU_FUCOM(Bitu op1, Bitu op2){
+       FPUD_COMPARE(fucompp)
+}
+
+static void FPU_FRNDINT(void){
+       FPUD_ARITH2(frndint)
+}
+
+static void FPU_FPREM(void){
+       FPUD_REMINDER(fprem)
+}
+
+static void FPU_FPREM1(void){
+       FPUD_REMINDER(fprem1)
+}
+
+static void FPU_FXAM(void){
+       FPUD_EXAMINE(fxam)
+       // handle empty registers (C1 set to sign in any way!)
+       if(fpu.tags[TOP] == TAG_Empty) {
+               FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1);
+               return;
+       }
+}
+
+static void FPU_F2XM1(void){
+       FPUD_TRIG(f2xm1)
+}
+
+static void FPU_FYL2X(void){
+       FPUD_FYL2X(fyl2x)
+}
+
+static void FPU_FYL2XP1(void){
+       FPUD_WITH_POP(fyl2xp1)
+}
+
+static void FPU_FSCALE(void){
+       FPUD_REMINDER(fscale)
+}
+
+
+static void FPU_FSTENV(PhysPt addr){
+       FPU_SET_TOP(TOP);
+       if(!cpu.code.big) {
+               mem_writew(addr+0,static_cast<Bit16u>(fpu.cw));
+               mem_writew(addr+2,static_cast<Bit16u>(fpu.sw));
+               mem_writew(addr+4,static_cast<Bit16u>(FPU_GetTag()));
+       } else { 
+               mem_writed(addr+0,static_cast<Bit32u>(fpu.cw));
+               mem_writed(addr+4,static_cast<Bit32u>(fpu.sw));
+               mem_writed(addr+8,static_cast<Bit32u>(FPU_GetTag()));
+       }
+}
+
+static void FPU_FLDENV(PhysPt addr){
+       Bit16u tag;
+       Bit32u tagbig;
+       Bitu cw;
+       if(!cpu.code.big) {
+               cw     = mem_readw(addr+0);
+               fpu.sw = mem_readw(addr+2);
+               tag    = mem_readw(addr+4);
+       } else { 
+               cw     = mem_readd(addr+0);
+               fpu.sw = (Bit16u)mem_readd(addr+4);
+               tagbig = mem_readd(addr+8);
+               tag    = static_cast<Bit16u>(tagbig);
+       }
+       FPU_SetTag(tag);
+       FPU_SetCW(cw);
+       TOP=FPU_GET_TOP();
+}
+
+static void FPU_FSAVE(PhysPt addr){
+       FPU_FSTENV(addr);
+       Bitu start=(cpu.code.big?28:14);
+       for(Bitu i=0;i<8;i++){
+               mem_writed(addr+start,fpu.p_regs[STV(i)].m1);
+               mem_writed(addr+start+4,fpu.p_regs[STV(i)].m2);
+               mem_writew(addr+start+8,fpu.p_regs[STV(i)].m3);
+               start+=10;
+       }
+       FPU_FINIT();
+}
+
+static void FPU_FRSTOR(PhysPt addr){
+       FPU_FLDENV(addr);
+       Bitu start=(cpu.code.big?28:14);
+       for(Bitu i=0;i<8;i++){
+               fpu.p_regs[STV(i)].m1 = mem_readd(addr+start);
+               fpu.p_regs[STV(i)].m2 = mem_readd(addr+start+4);
+               fpu.p_regs[STV(i)].m3 = mem_readw(addr+start+8);
+               start+=10;
+       }
+}
+
+
+static void FPU_FXTRACT(void) {
+       FPUD_XTRACT
+}
+
+static void FPU_FCHS(void){
+       FPUD_TRIG(fchs)
+}
+
+static void FPU_FABS(void){
+       FPUD_TRIG(fabs)
+}
+
+static void FPU_FTST(void){
+       FPUD_EXAMINE(ftst)
+}
+
+static void FPU_FLD1(void){
+       FPUD_LOAD_CONST(fld1)
+}
+
+static void FPU_FLDL2T(void){
+       FPUD_LOAD_CONST(fldl2t)
+}
+
+static void FPU_FLDL2E(void){
+       FPUD_LOAD_CONST(fldl2e)
+}
+
+static void FPU_FLDPI(void){
+       FPUD_LOAD_CONST(fldpi)
+}
+
+static void FPU_FLDLG2(void){
+       FPUD_LOAD_CONST(fldlg2)
+}
+
+static void FPU_FLDLN2(void){
+       FPUD_LOAD_CONST(fldln2)
+}
+
+static void FPU_FLDZ(void){
+       FPUD_LOAD_CONST(fldz)
+       fpu.tags[TOP]=TAG_Zero;
+}
diff --git a/dosbox/inout.h b/dosbox/inout.h
new file mode 100644 (file)
index 0000000..798e9db
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  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: inout.h,v 1.13 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#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);
+       ~IO_ReadHandleObject();
+};
+class IO_WriteHandleObject: private IO_Base{
+public:
+       void Install(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
+       ~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/dosbox/instructions.h b/dosbox/instructions.h
new file mode 100644 (file)
index 0000000..1696997
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+ *  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.
+ */
+
+/* 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/dosbox/keyboard.cpp b/dosbox/keyboard.cpp
new file mode 100644 (file)
index 0000000..5f86de0
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ *  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: keyboard.cpp,v 1.41 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#include "dosbox.h"
+#include "keyboard.h"
+#include "inout.h"
+#include "pic.h"
+#include "mem.h"
+#include "setup.h"
+//#include "mixer.h"
+//#include "timer.h"
+
+extern void write_log(const char*,...);
+
+#define KEYBUFSIZE 32
+#define KEYDELAY 0.300f                        //Considering 20-30 khz serial clock and 11 bits/char
+
+enum KeyCommands {
+       CMD_NONE,
+       CMD_SETLEDS,
+       CMD_SETTYPERATE,
+       CMD_SETOUTPORT,
+       CMD_JUMPERS
+};
+
+static struct {
+       Bit8u buffer[KEYBUFSIZE];
+       Bitu used;
+       Bitu pos;
+       struct {
+//             KBD_KEYS key;
+               Bitu wait;
+               Bitu pause,rate;
+       } repeat;
+       KeyCommands command;
+       Bit8u p60data;
+       bool p60changed;
+       bool active;
+       bool scanning;
+       bool scheduled;
+       Bit8u outport;
+} keyb;
+
+extern void x86_doirq(unsigned char);
+
+bool x86_is_keyboard(void)
+{
+       return keyb.p60changed;
+}
+
+static void KEYBOARD_SetPort60(Bit8u val) {
+       keyb.p60changed=true;
+       keyb.p60data=val;
+//     if (machine==MCH_PCJR)
+//             PIC_ActivateIRQ(6);
+//     else
+//             PIC_ActivateIRQ(1);
+       x86_doirq(1);
+}
+
+static void KEYBOARD_TransferBuffer(Bitu val) {
+       keyb.scheduled=false;
+       if (!keyb.used) {
+               LOG(LOG_KEYBOARD,LOG_NORMAL)("Transfer started with empty buffer");
+               return;
+       }
+       KEYBOARD_SetPort60(keyb.buffer[keyb.pos]);
+       if (++keyb.pos>=KEYBUFSIZE) keyb.pos-=KEYBUFSIZE;
+       keyb.used--;
+}
+
+
+void KEYBOARD_ClrBuffer(void) {
+       keyb.used=0;
+       keyb.pos=0;
+//     PIC_RemoveEvents(KEYBOARD_TransferBuffer);
+       keyb.scheduled=false;
+}
+
+void KEYBOARD_AddBuffer(Bit8u data) {
+       if (keyb.used>=KEYBUFSIZE) {
+               LOG(LOG_KEYBOARD,LOG_NORMAL)("Buffer full, dropping code");
+               return;
+       }
+       Bitu start=keyb.pos+keyb.used;
+       if (start>=KEYBUFSIZE) start-=KEYBUFSIZE;
+       keyb.buffer[start]=data;
+       keyb.used++;
+       /* Start up an event to start the first IRQ */
+       if (!keyb.scheduled && !keyb.p60changed) {
+               keyb.scheduled=true;
+               KEYBOARD_TransferBuffer(0);
+//             PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
+       }
+}
+
+
+static Bitu read_p60(Bitu port,Bitu iolen) {
+       keyb.p60changed=false;
+       if (!keyb.scheduled && keyb.used) {
+               keyb.scheduled=true;
+               KEYBOARD_TransferBuffer(0);
+//             PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
+       }
+       return keyb.p60data;
+}      
+
+void x86_init_reset(void);
+uint8_t x86_get_jumpers(void);
+
+static void write_p60(Bitu port,Bitu val,Bitu iolen) {
+       switch (keyb.command) {
+       case CMD_NONE:  /* None */
+               /* No active command this would normally get sent to the keyboard then */
+               KEYBOARD_ClrBuffer();
+               switch (val) {
+               case 0xed:      /* Set Leds */
+                       keyb.command=CMD_SETLEDS;
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       break;
+               case 0xee:      /* Echo */
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       break;
+               case 0xf2:      /* Identify keyboard */
+                       /* AT's just send acknowledge */
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       break;
+               case 0xf3: /* Typematic rate programming */
+                       keyb.command=CMD_SETTYPERATE;
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       break;
+               case 0xf4:      /* Enable keyboard,clear buffer, start scanning */
+                       LOG(LOG_KEYBOARD,LOG_NORMAL)("Clear buffer,enable Scaning");
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       keyb.scanning=true;
+                       break;
+               case 0xf5:       /* Reset keyboard and disable scanning */
+                       LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, disable scanning");                        
+                       keyb.scanning=false;
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       break;
+               case 0xf6:      /* Reset keyboard and enable scanning */
+                       LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, enable scanning");
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       keyb.scanning=false;
+                       break;
+               case 0xff:
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+                       KEYBOARD_AddBuffer(0xaa);
+                       break;
+               default:
+                       /* Just always acknowledge strange commands */
+                       LOG(LOG_KEYBOARD,LOG_ERROR)("60:Unhandled command %X",val);
+                       KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+               }
+               return;
+       case CMD_SETOUTPORT:
+               MEM_A20_Enable((val & 2)>0);
+               keyb.outport = val;
+               if (!(val & 1)) {
+                       x86_init_reset();
+               }
+               keyb.command = CMD_NONE;
+               break;
+       case CMD_SETTYPERATE: 
+               {
+                       static const int delay[] = { 250, 500, 750, 1000 };
+                       static const int repeat[] = 
+                               { 33,37,42,46,50,54,58,63,67,75,83,92,100,
+                                 109,118,125,133,149,167,182,200,217,233,
+                                 250,270,303,333,370,400,435,476,500 };
+                       keyb.repeat.pause = delay[(val>>5)&3];
+                       keyb.repeat.rate = repeat[val&0x1f];
+                       keyb.command=CMD_NONE;
+               }
+               /* Fallthrough! as setleds does what we want */
+       case CMD_SETLEDS:
+               keyb.command=CMD_NONE;
+               KEYBOARD_ClrBuffer();
+               KEYBOARD_AddBuffer(0xfa);       /* Acknowledge */
+               break;
+       }
+}
+
+static Bit8u port_61_data = 0;
+static Bitu read_p61(Bitu port,Bitu iolen) {
+       port_61_data^=0x20;
+       port_61_data^=0x10;
+       return port_61_data;
+}
+
+extern void TIMER_SetGate2(bool);
+static void write_p61(Bitu port,Bitu val,Bitu iolen) {
+       if ((port_61_data ^ val) & 3) {
+               if((port_61_data ^ val) & 1)
+                       TIMER_SetGate2(val&0x1);
+//             PCSPEAKER_SetType(val & 3);
+       }
+       port_61_data = val;
+}
+
+static void write_p64(Bitu port,Bitu val,Bitu iolen) {
+       switch (val) {
+       case 0xae:              /* Activate keyboard */
+               keyb.active=true;
+               if (keyb.used && !keyb.scheduled && !keyb.p60changed) {
+                       keyb.scheduled=true;
+                       KEYBOARD_TransferBuffer(0);
+                       //PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
+               }
+               LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated");
+               break;
+       case 0xad:              /* Deactivate keyboard */
+               keyb.active=false;
+               LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated");
+               break;
+       case 0xc0: // read config jumpers
+               KEYBOARD_SetPort60(x86_get_jumpers());
+               break;
+       case 0xd0:              /* Outport on buffer */
+               KEYBOARD_SetPort60(MEM_A20_Enabled() ? 0x02 : 0);
+               break;
+       case 0xd1:              /* Write to outport */
+               keyb.command=CMD_SETOUTPORT;
+               break;
+       case 0xaa:
+               KEYBOARD_SetPort60(0x55);
+               break;
+       case 0xe0:
+               // bit 0 = clock line state, 1 = data line state
+               KEYBOARD_SetPort60((keyb.outport & 30) ? 2 : 3);
+               break;
+       case 0xfe: // pulse reset pin
+       case 0xfc:
+       case 0xfa:
+       case 0xf8:
+       case 0xf6:
+       case 0xf4:
+       case 0xf2:
+       case 0xf0:
+               x86_init_reset();
+               break;
+       default:
+               LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val);
+               break;
+       }
+}
+
+static Bitu read_p64(Bitu port,Bitu iolen) {
+       Bit8u status= (keyb.outport & 0x7c) | (keyb.p60changed ? 0x1 : 0x0);
+       return status;
+}
+
+Bitu x86_in_keyboard(Bitu port)
+{
+       Bitu v = 0xff;
+       switch (port) {
+               case 0x60:
+               v = read_p60(port, 1);
+               break;
+               case 0x61:
+               v = read_p61(port, 1);
+               break;
+               case 0x64:
+               v = read_p64(port, 1);
+               break;
+       }
+       //write_log("read %02x %02x\n", port, v);
+       return v;
+}
+
+void x86_out_keyboard(Bitu port, Bitu val)
+{
+       //write_log("write %02x %02x\n", port, val);
+       switch(port)
+       {
+               case 0x60:
+               write_p60(port, val, 1);
+               break;
+               case 0x61:
+               write_p61(port, val, 1);
+               break;
+               case 0x64:
+               write_p64(port, val, 1);
+               break;
+       }
+}
+
+#if 0
+void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
+       Bit8u ret=0;bool extend=false;
+       switch (keytype) {
+       case KBD_esc:ret=1;break;
+       case KBD_1:ret=2;break;
+       case KBD_2:ret=3;break;
+       case KBD_3:ret=4;break;         
+       case KBD_4:ret=5;break;
+       case KBD_5:ret=6;break;
+       case KBD_6:ret=7;break;         
+       case KBD_7:ret=8;break;
+       case KBD_8:ret=9;break;
+       case KBD_9:ret=10;break;                
+       case KBD_0:ret=11;break;
+
+       case KBD_minus:ret=12;break;
+       case KBD_equals:ret=13;break;
+       case KBD_backspace:ret=14;break;
+       case KBD_tab:ret=15;break;
+
+       case KBD_q:ret=16;break;                
+       case KBD_w:ret=17;break;
+       case KBD_e:ret=18;break;                
+       case KBD_r:ret=19;break;
+       case KBD_t:ret=20;break;                
+       case KBD_y:ret=21;break;
+       case KBD_u:ret=22;break;                
+       case KBD_i:ret=23;break;
+       case KBD_o:ret=24;break;                
+       case KBD_p:ret=25;break;
+
+       case KBD_leftbracket:ret=26;break;
+       case KBD_rightbracket:ret=27;break;
+       case KBD_enter:ret=28;break;
+       case KBD_leftctrl:ret=29;break;
+
+       case KBD_a:ret=30;break;
+       case KBD_s:ret=31;break;
+       case KBD_d:ret=32;break;
+       case KBD_f:ret=33;break;
+       case KBD_g:ret=34;break;                
+       case KBD_h:ret=35;break;                
+       case KBD_j:ret=36;break;
+       case KBD_k:ret=37;break;                
+       case KBD_l:ret=38;break;
+
+       case KBD_semicolon:ret=39;break;
+       case KBD_quote:ret=40;break;
+       case KBD_grave:ret=41;break;
+       case KBD_leftshift:ret=42;break;
+       case KBD_backslash:ret=43;break;
+       case KBD_z:ret=44;break;
+       case KBD_x:ret=45;break;
+       case KBD_c:ret=46;break;
+       case KBD_v:ret=47;break;
+       case KBD_b:ret=48;break;
+       case KBD_n:ret=49;break;
+       case KBD_m:ret=50;break;
+
+       case KBD_comma:ret=51;break;
+       case KBD_period:ret=52;break;
+       case KBD_slash:ret=53;break;
+       case KBD_rightshift:ret=54;break;
+       case KBD_kpmultiply:ret=55;break;
+       case KBD_leftalt:ret=56;break;
+       case KBD_space:ret=57;break;
+       case KBD_capslock:ret=58;break;
+
+       case KBD_f1:ret=59;break;
+       case KBD_f2:ret=60;break;
+       case KBD_f3:ret=61;break;
+       case KBD_f4:ret=62;break;
+       case KBD_f5:ret=63;break;
+       case KBD_f6:ret=64;break;
+       case KBD_f7:ret=65;break;
+       case KBD_f8:ret=66;break;
+       case KBD_f9:ret=67;break;
+       case KBD_f10:ret=68;break;
+
+       case KBD_numlock:ret=69;break;
+       case KBD_scrolllock:ret=70;break;
+
+       case KBD_kp7:ret=71;break;
+       case KBD_kp8:ret=72;break;
+       case KBD_kp9:ret=73;break;
+       case KBD_kpminus:ret=74;break;
+       case KBD_kp4:ret=75;break;
+       case KBD_kp5:ret=76;break;
+       case KBD_kp6:ret=77;break;
+       case KBD_kpplus:ret=78;break;
+       case KBD_kp1:ret=79;break;
+       case KBD_kp2:ret=80;break;
+       case KBD_kp3:ret=81;break;
+       case KBD_kp0:ret=82;break;
+       case KBD_kpperiod:ret=83;break;
+
+       case KBD_extra_lt_gt:ret=86;break;
+       case KBD_f11:ret=87;break;
+       case KBD_f12:ret=88;break;
+
+       //The Extended keys
+
+       case KBD_kpenter:extend=true;ret=28;break;
+       case KBD_rightctrl:extend=true;ret=29;break;
+       case KBD_kpdivide:extend=true;ret=53;break;
+       case KBD_rightalt:extend=true;ret=56;break;
+       case KBD_home:extend=true;ret=71;break;
+       case KBD_up:extend=true;ret=72;break;
+       case KBD_pageup:extend=true;ret=73;break;
+       case KBD_left:extend=true;ret=75;break;
+       case KBD_right:extend=true;ret=77;break;
+       case KBD_end:extend=true;ret=79;break;
+       case KBD_down:extend=true;ret=80;break;
+       case KBD_pagedown:extend=true;ret=81;break;
+       case KBD_insert:extend=true;ret=82;break;
+       case KBD_delete:extend=true;ret=83;break;
+       case KBD_pause:
+               KEYBOARD_AddBuffer(0xe1);
+               KEYBOARD_AddBuffer(29|(pressed?0:0x80));
+               KEYBOARD_AddBuffer(69|(pressed?0:0x80));
+               return;
+       case KBD_printscreen:
+               /* Not handled yet. But usuable in mapper for special events */
+               return;
+       default:
+               E_Exit("Unsupported key press");
+               break;
+       }
+       /* Add the actual key in the keyboard queue */
+       if (pressed) {
+               if (keyb.repeat.key==keytype) keyb.repeat.wait=keyb.repeat.rate;                
+               else keyb.repeat.wait=keyb.repeat.pause;
+               keyb.repeat.key=keytype;
+       } else {
+               keyb.repeat.key=KBD_NONE;
+               keyb.repeat.wait=0;
+               ret+=128;
+       }
+       if (extend) KEYBOARD_AddBuffer(0xe0); 
+       KEYBOARD_AddBuffer(ret);
+}
+
+static void KEYBOARD_TickHandler(void) {
+       if (keyb.repeat.wait) {
+               keyb.repeat.wait--;
+               if (!keyb.repeat.wait) KEYBOARD_AddKey(keyb.repeat.key,true);
+       }
+}
+#endif
+
+void KEYBOARD_Init(Section* sec) {
+#if 0
+       IO_RegisterWriteHandler(0x60,write_p60,IO_MB);
+       IO_RegisterReadHandler(0x60,read_p60,IO_MB);
+       IO_RegisterWriteHandler(0x61,write_p61,IO_MB);
+       IO_RegisterReadHandler(0x61,read_p61,IO_MB);
+       IO_RegisterWriteHandler(0x64,write_p64,IO_MB);
+       IO_RegisterReadHandler(0x64,read_p64,IO_MB);
+#endif
+//     TIMER_AddTickHandler(&KEYBOARD_TickHandler);
+       write_p61(0,0,0);
+       /* Init the keyb struct */
+       keyb.active=true;
+       keyb.scanning=true;
+       keyb.command=CMD_NONE;
+       keyb.p60changed=false;
+//     keyb.repeat.key=KBD_NONE;
+       keyb.repeat.pause=500;
+       keyb.repeat.rate=33;
+       keyb.repeat.wait=0;
+       KEYBOARD_ClrBuffer();
+}
diff --git a/dosbox/lazyflags.h b/dosbox/lazyflags.h
new file mode 100644 (file)
index 0000000..a2a031d
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  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.
+ */
+
+#if !defined __LAZYFLAGS_H
+#define __LAZYFLAG_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);
+
+#include "regs.h"
+
+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/dosbox/logging.h b/dosbox/logging.h
new file mode 100644 (file)
index 0000000..ae3daae
--- /dev/null
@@ -0,0 +1,67 @@
+#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_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* , 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*)                         { }
+
+
+}; //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/dosbox/mem.h b/dosbox/mem.h
new file mode 100644 (file)
index 0000000..c022626
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ *  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.
+ */
+
+#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)
+
+void bridge_mono_hit(void);
+void bridge_color_hit(void);
+extern HostPt mono_start, mono_end, color_start, color_end;
+static INLINE void bridge_special_addr_check(HostPt off)
+{
+       if (off >= mono_start && off < mono_end)
+               bridge_mono_hit();
+       if (off >= color_start && off < color_end)
+               bridge_color_hit();
+}
+
+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) {
+       bridge_special_addr_check(off);
+       off[0]=val;
+}
+static INLINE void host_writew(HostPt off,Bit16u val) {
+       bridge_special_addr_check(off);
+       off[0]=(Bit8u)(val);
+       off[1]=(Bit8u)(val >> 8);
+}
+static INLINE void host_writed(HostPt off,Bit32u val) {
+       bridge_special_addr_check(off);
+       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/dosbox/modrm.cpp b/dosbox/modrm.cpp
new file mode 100644 (file)
index 0000000..bbac41e
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *  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.
+ */
+
+#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/dosbox/modrm.h b/dosbox/modrm.h
new file mode 100644 (file)
index 0000000..60482bf
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  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.
+ */
+
+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/dosbox/paging.cpp b/dosbox/paging.cpp
new file mode 100644 (file)
index 0000000..e3088ed
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ *  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: paging.cpp,v 1.36 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#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) {
+       return 
+               (readb(addr+0) << 0) |
+               (readb(addr+1) << 8);
+}
+Bitu PageHandler::readd(PhysPt addr) {
+       return 
+               (readb(addr+0) << 0)  |
+               (readb(addr+1) << 8)  |
+               (readb(addr+2) << 16) |
+               (readb(addr+3) << 24);
+}
+
+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 disable 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);
+}
diff --git a/dosbox/paging.h b/dosbox/paging.h
new file mode 100644 (file)
index 0000000..f7198f8
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ *  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: paging.h,v 1.33 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#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/dosbox/pic.cpp b/dosbox/pic.cpp
new file mode 100644 (file)
index 0000000..f6c1801
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ *  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: pic.cpp,v 1.44 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#include <list>
+
+#include "dosbox.h"
+#include "inout.h"
+#include "cpu.h"
+#include "callback.h"
+#include "pic.h"
+//#include "timer.h"
+#include "setup.h"
+
+#define PIC_QUEUESIZE 512
+
+struct IRQ_Block {
+       bool masked;
+       bool active;
+       bool inservice;
+       Bitu vector;
+};
+
+struct PIC_Controller {
+       Bitu icw_words;
+       Bitu icw_index;
+       Bitu masked;
+
+       bool special;
+       bool auto_eoi;
+       bool rotate_on_auto_eoi;
+       bool single;
+       bool request_issr;
+       Bit8u vector_base;
+};
+
+Bitu PIC_Ticks=0;
+Bitu PIC_IRQCheck;
+Bitu PIC_IRQOnSecondPicActive;
+Bitu PIC_IRQActive;
+
+
+static IRQ_Block irqs[16];
+static PIC_Controller pics[2];
+static bool PIC_Special_Mode = false; //Saves one compare in the pic_run_irqloop
+struct PICEntry {
+       float index;
+       Bitu value;
+       PIC_EventHandler pic_event;
+       PICEntry * next;
+};
+
+static struct {
+       PICEntry entries[PIC_QUEUESIZE];
+       PICEntry * free_entry;
+       PICEntry * next_entry;
+} pic_queue;
+
+void x86_ack_keyboard(void);
+
+static void write_command(Bitu port,Bitu val,Bitu iolen) {
+       PIC_Controller * pic=&pics[port==0x20 ? 0 : 1];
+       Bitu irq_base=port==0x20 ? 0 : 8;
+       Bitu i;
+       static Bit16u IRQ_priority_table[16] = 
+               { 0,1,2,8,9,10,11,12,13,14,15,3,4,5,6,7 };
+       if (GCC_UNLIKELY(val&0x10)) {           // ICW1 issued
+               if (val&0x04) E_Exit("PIC: 4 byte interval not handled");
+               if (val&0x08) E_Exit("PIC: level triggered mode not handled");
+               if (val&0xe0) E_Exit("PIC: 8080/8085 mode not handled");
+               pic->single=(val&0x02)==0x02;
+               pic->icw_index=1;                       // next is ICW2
+               pic->icw_words=2 + (val&0x01);  // =3 if ICW4 needed
+       } else if (GCC_UNLIKELY(val&0x08)) {    // OCW3 issued
+               if (val&0x04) E_Exit("PIC: poll command not handled");
+               if (val&0x02) {         // function select
+                       if (val&0x01) pic->request_issr=true;   /* select read interrupt in-service register */
+                       else pic->request_issr=false;                   /* select read interrupt request register */
+               }
+               if (val&0x40) {         // special mask select
+                       if (val&0x20) pic->special=true;
+                       else pic->special=false;
+                       if(pic[0].special || pics[1].special) 
+                               PIC_Special_Mode = true; else 
+                               PIC_Special_Mode = false;
+                       if (PIC_IRQCheck) { //Recheck irqs
+                               CPU_CycleLeft += CPU_Cycles;
+                               CPU_Cycles = 0;
+                       }
+                       LOG(LOG_PIC,LOG_NORMAL)("port %X : special mask %s",port,(pic->special)?"ON":"OFF");
+               }
+       } else {        // OCW2 issued
+               if (val&0x20) {         // EOI commands
+                       if (GCC_UNLIKELY(val&0x80)) E_Exit("rotate mode not supported");
+                       if (val&0x40) {         // specific EOI
+                               if (PIC_IRQActive==(irq_base+val-0x60U)) {
+                                       irqs[PIC_IRQActive].inservice=false;
+                                       if (PIC_IRQActive == 1)
+                                               x86_ack_keyboard();
+                                       PIC_IRQActive=PIC_NOIRQ;
+                                       for (i=0; i<=15; i++) {
+                                               if (irqs[IRQ_priority_table[i]].inservice) {
+                                                       PIC_IRQActive=IRQ_priority_table[i];
+                                                       break;
+                                               }
+                                       }
+                               }
+//                             if (val&0x80);  // perform rotation
+                       } else {                // nonspecific EOI
+                               if (PIC_IRQActive<(irq_base+8)) {
+                                       irqs[PIC_IRQActive].inservice=false;
+                                       if (PIC_IRQActive == 1)
+                                               x86_ack_keyboard();
+                                       PIC_IRQActive=PIC_NOIRQ;
+                                       for (i=0; i<=15; i++){
+                                               if(GCC_UNLIKELY(irqs[IRQ_priority_table[i]].inservice)) {
+                                                       PIC_IRQActive=IRQ_priority_table[i];
+                                                       break;
+                                               }
+                                       }
+                               }
+//                             if (val&0x80);  // perform rotation
+                       }
+               } else {
+                       if ((val&0x40)==0) {            // rotate in auto EOI mode
+                               if (val&0x80) pic->rotate_on_auto_eoi=true;
+                               else pic->rotate_on_auto_eoi=false;
+                       } else if (val&0x80) {
+                               LOG(LOG_PIC,LOG_NORMAL)("set priority command not handled");
+                       }       // else NOP command
+               }
+       }       // end OCW2
+}
+
+static void write_data(Bitu port,Bitu val,Bitu iolen) {
+       PIC_Controller * pic=&pics[port==0x21 ? 0 : 1];
+       Bitu irq_base=(port==0x21) ? 0 : 8;
+       Bitu i;
+       bool old_irq2_mask = irqs[2].masked;
+       switch(pic->icw_index) {
+       case 0:                        /* mask register */
+               LOG(LOG_PIC,LOG_NORMAL)("%d mask %X",port==0x21 ? 0 : 1,val);
+               for (i=0;i<=7;i++) {
+                       irqs[i+irq_base].masked=(val&(1<<i))>0;
+                       if(port==0x21) {
+                               if (irqs[i+irq_base].active && !irqs[i+irq_base].masked) PIC_IRQCheck|=(1 << (i+irq_base));
+                               else PIC_IRQCheck&=~(1 << (i+irq_base));
+                       } else {
+                               if (irqs[i+irq_base].active && !irqs[i+irq_base].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i+irq_base));
+                               else PIC_IRQCheck&=~(1 << (i+irq_base));
+                       }
+               }
+#if 0
+               if (machine==MCH_PCJR) {
+                       /* irq6 cannot be disabled as it serves as pseudo-NMI */
+                       irqs[6].masked=false;
+               }
+#endif
+               if(irqs[2].masked != old_irq2_mask) {
+               /* Irq 2 mask has changed recheck second pic */
+                       for(i=8;i<=15;i++) {
+                               if (irqs[i].active && !irqs[i].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i));
+                               else PIC_IRQCheck&=~(1 << (i));
+                       }
+               }
+               if (PIC_IRQCheck) {
+                       CPU_CycleLeft+=CPU_Cycles;
+                       CPU_Cycles=0;
+               }
+               break;
+       case 1:                        /* icw2          */
+               LOG(LOG_PIC,LOG_NORMAL)("%d:Base vector %X",port==0x21 ? 0 : 1,val);
+               for (i=0;i<=7;i++) {
+                       irqs[i+irq_base].vector=(val&0xf8)+i;
+               };
+               if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0;
+               else if(pic->single) pic->icw_index=3;          /* skip ICW3 in single mode */
+               break;
+       case 2:                                                 /* icw 3 */
+               LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 3 %X",port==0x21 ? 0 : 1,val);
+               if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0;
+               break;
+       case 3:                                                 /* icw 4 */
+               /*
+                       0           1 8086/8080  0 mcs-8085 mode
+                       1           1 Auto EOI   0 Normal EOI
+                       2-3        0x Non buffer Mode 
+                                  10 Buffer Mode Slave 
+                                  11 Buffer mode Master        
+                       4               Special/Not Special nested mode 
+               */
+               pic->auto_eoi=(val & 0x2)>0;
+               
+               LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",port==0x21 ? 0 : 1,val);
+
+               if ((val&0x01)==0) E_Exit("PIC:ICW4: %x, 8085 mode not handled",val);
+               if ((val&0x10)!=0) LOG_MSG("PIC:ICW4: %x, special fully-nested mode not handled",val);
+
+               if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0;
+               break;
+       default:
+               LOG(LOG_PIC,LOG_NORMAL)("ICW HUH? %X",val);
+               break;
+       }
+}
+
+
+static Bitu read_command(Bitu port,Bitu iolen) {
+       PIC_Controller * pic=&pics[port==0x20 ? 0 : 1];
+       Bitu irq_base=(port==0x20) ? 0 : 8;
+       Bitu i;Bit8u ret=0;Bit8u b=1;
+       if (pic->request_issr) {
+               for (i=irq_base;i<irq_base+8;i++) {
+                       if (irqs[i].inservice) ret|=b;
+                       b <<= 1;
+               }
+       } else {
+               for (i=irq_base;i<irq_base+8;i++) {
+                       if (irqs[i].active)     ret|=b;
+                       b <<= 1;
+               }
+               if (irq_base==0 && (PIC_IRQCheck&0xff00)) ret |=4;
+       }
+       return ret;
+}
+
+static Bitu read_data(Bitu port,Bitu iolen) {
+       Bitu irq_base=(port==0x21) ? 0 : 8;
+       Bitu i;Bit8u ret=0;Bit8u b=1;
+       for (i=irq_base;i<=irq_base+7;i++) {
+               if (irqs[i].masked)     ret|=b;
+               b <<= 1;
+       }
+       return ret;
+}
+
+
+void PIC_ActivateIRQ(Bitu irq) {
+       if( irq < 8 ) {
+               irqs[irq].active = true;
+               if (!irqs[irq].masked) {
+                       PIC_IRQCheck|=(1 << irq);
+               }
+       } else  if (irq < 16) {
+               irqs[irq].active = true;
+               PIC_IRQOnSecondPicActive|=(1 << irq);
+               if (!irqs[irq].masked && !irqs[2].masked) {
+                       PIC_IRQCheck|=(1 << irq);
+               }
+       }
+}
+
+void PIC_DeActivateIRQ(Bitu irq) {
+       if (irq<16) {
+               irqs[irq].active=false;
+               PIC_IRQCheck&=~(1 << irq);
+               PIC_IRQOnSecondPicActive&=~(1 << irq);
+       }
+}
+static inline bool PIC_startIRQ(Bitu i) {
+       /* irqs on second pic only if irq 2 isn't masked */
+       if( i > 7 && irqs[2].masked) return false;
+       irqs[i].active = false;
+       PIC_IRQCheck&= ~(1 << i);
+       PIC_IRQOnSecondPicActive&= ~(1 << i);
+       CPU_HW_Interrupt(irqs[i].vector);
+       Bitu pic=(i&8)>>3;
+       if (!pics[pic].auto_eoi) { //irq 0-7 => pic 0 else pic 1 
+               PIC_IRQActive = i;
+               irqs[i].inservice = true;
+       } else if (GCC_UNLIKELY(pics[pic].rotate_on_auto_eoi)) {
+               E_Exit("rotate on auto EOI not handled");
+       }
+       return true;
+}
+
+void PIC_runIRQs(void) {
+       if (!GETFLAG(IF)) return;
+       if (GCC_UNLIKELY(!PIC_IRQCheck)) return;
+       if (GCC_UNLIKELY(cpudecoder==CPU_Core_Normal_Trap_Run)) return;
+
+       static Bitu IRQ_priority_order[16] = 
+               { 0,1,2,8,9,10,11,12,13,14,15,3,4,5,6,7 };
+       static Bit16u IRQ_priority_lookup[17] =
+               { 0,1,2,11,12,13,14,15,3,4,5,6,7,8,9,10,16 };
+       Bit16u activeIRQ = PIC_IRQActive;
+       if (activeIRQ == PIC_NOIRQ) activeIRQ = 16;
+       /* Get the priority of the active irq */
+       Bit16u Priority_Active_IRQ = IRQ_priority_lookup[activeIRQ];
+
+       Bitu i,j;
+       /* j is the priority (walker)
+        * i is the irq at the current priority */
+
+       /* If one of the pics is in special mode use a check that cares for that. */
+       if(!PIC_Special_Mode) {
+               for (j = 0; j < Priority_Active_IRQ; j++) {
+                       i = IRQ_priority_order[j];
+                       if (!irqs[i].masked && irqs[i].active) {
+                               if(GCC_LIKELY(PIC_startIRQ(i))) return;
+                       }
+               }
+       } else {        /* Special mode variant */
+               for (j = 0; j<= 15; j++) {
+                       i = IRQ_priority_order[j];
+                       if ( (j < Priority_Active_IRQ) || (pics[ ((i&8)>>3) ].special) ) {
+                               if (!irqs[i].masked && irqs[i].active) {
+                                       /* the irq line is active. it's not masked and
+                                        * the irq is allowed priority wise. So let's start it */
+                                       /* If started successfully return, else go for the next */
+                                       if(PIC_startIRQ(i)) return;
+                               }
+                       }
+               }
+       }
+}
+
+void PIC_SetIRQMask(Bitu irq, bool masked) {
+       if(irqs[irq].masked == masked) return;  /* Do nothing if mask doesn't change */
+       bool old_irq2_mask = irqs[2].masked;
+       irqs[irq].masked=masked;
+       if(irq < 8) {
+               if (irqs[irq].active && !irqs[irq].masked) { 
+                       PIC_IRQCheck|=(1 << (irq));
+               } else { 
+                       PIC_IRQCheck&=~(1 << (irq));
+               }
+       } else {
+               if (irqs[irq].active && !irqs[irq].masked && !irqs[2].masked) {
+                       PIC_IRQCheck|=(1 << (irq));
+               } else { 
+                       PIC_IRQCheck&=~(1 << (irq));
+               }
+       }
+       if(irqs[2].masked != old_irq2_mask) {
+       /* Irq 2 mask has changed recheck second pic */
+               for(Bitu i=8;i<=15;i++) {
+                       if (irqs[i].active && !irqs[i].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i));
+                       else PIC_IRQCheck&=~(1 << (i));
+               }
+       }
+       if (PIC_IRQCheck) {
+               CPU_CycleLeft+=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+}
+
+static void AddEntry(PICEntry * entry) {
+       PICEntry * find_entry=pic_queue.next_entry;
+       if (GCC_UNLIKELY(find_entry ==0)) {
+               entry->next=0;
+               pic_queue.next_entry=entry;
+       } else if (find_entry->index>entry->index) {
+               pic_queue.next_entry=entry;
+               entry->next=find_entry;
+       } else while (find_entry) {
+               if (find_entry->next) {
+                       /* See if the next index comes later than this one */
+                       if (find_entry->next->index > entry->index) {
+                               entry->next=find_entry->next;
+                               find_entry->next=entry;
+                               break;
+                       } else {
+                               find_entry=find_entry->next;
+                       }
+               } else {
+                       entry->next=find_entry->next;
+                       find_entry->next=entry;
+                       break;
+               }
+       }
+       Bits cycles=PIC_MakeCycles(pic_queue.next_entry->index-PIC_TickIndex());
+       if (cycles<CPU_Cycles) {
+               CPU_CycleLeft+=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+}
+static bool InEventService = false;
+static float srv_lag = 0;
+
+void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val) {
+       if (GCC_UNLIKELY(!pic_queue.free_entry)) {
+               LOG(LOG_PIC,LOG_ERROR)("Event queue full");
+               return;
+       }
+       PICEntry * entry=pic_queue.free_entry;
+       if(InEventService) entry->index = delay + srv_lag;
+       else entry->index = delay + PIC_TickIndex();
+
+       entry->pic_event=handler;
+       entry->value=val;
+       pic_queue.free_entry=pic_queue.free_entry->next;
+       AddEntry(entry);
+}
+
+void PIC_RemoveSpecificEvents(PIC_EventHandler handler, Bitu val) {
+       PICEntry * entry=pic_queue.next_entry;
+       PICEntry * prev_entry;
+       prev_entry = 0;
+       while (entry) {
+               if (GCC_UNLIKELY((entry->pic_event == handler)) && (entry->value == val)) {
+                       if (prev_entry) {
+                               prev_entry->next=entry->next;
+                               entry->next=pic_queue.free_entry;
+                               pic_queue.free_entry=entry;
+                               entry=prev_entry->next;
+                               continue;
+                       } else {
+                               pic_queue.next_entry=entry->next;
+                               entry->next=pic_queue.free_entry;
+                               pic_queue.free_entry=entry;
+                               entry=pic_queue.next_entry;
+                               continue;
+                       }
+               }
+               prev_entry=entry;
+               entry=entry->next;
+       }       
+}
+
+void PIC_RemoveEvents(PIC_EventHandler handler) {
+       PICEntry * entry=pic_queue.next_entry;
+       PICEntry * prev_entry;
+       prev_entry=0;
+       while (entry) {
+               if (GCC_UNLIKELY(entry->pic_event==handler)) {
+                       if (prev_entry) {
+                               prev_entry->next=entry->next;
+                               entry->next=pic_queue.free_entry;
+                               pic_queue.free_entry=entry;
+                               entry=prev_entry->next;
+                               continue;
+                       } else {
+                               pic_queue.next_entry=entry->next;
+                               entry->next=pic_queue.free_entry;
+                               pic_queue.free_entry=entry;
+                               entry=pic_queue.next_entry;
+                               continue;
+                       }
+               }
+               prev_entry=entry;
+               entry=entry->next;
+       }       
+}
+
+
+bool PIC_RunQueue(void) {
+       /* Check to see if a new milisecond needs to be started */
+       CPU_CycleLeft+=CPU_Cycles;
+       CPU_Cycles=0;
+       if (CPU_CycleLeft<=0) {
+               return false;
+       }
+       /* Check the queue for an entry */
+       Bits index_nd=PIC_TickIndexND();
+       InEventService = true;
+       while (pic_queue.next_entry && (pic_queue.next_entry->index*CPU_CycleMax<=index_nd)) {
+               PICEntry * entry=pic_queue.next_entry;
+               pic_queue.next_entry=entry->next;
+
+               srv_lag = entry->index;
+               (entry->pic_event)(entry->value); // call the event handler
+
+               /* Put the entry in the free list */
+               entry->next=pic_queue.free_entry;
+               pic_queue.free_entry=entry;
+       }
+       InEventService = false;
+
+       /* Check when to set the new cycle end */
+       if (pic_queue.next_entry) {
+               Bits cycles=(Bits)(pic_queue.next_entry->index*CPU_CycleMax-index_nd);
+               if (GCC_UNLIKELY(!cycles)) cycles=1;
+               if (cycles<CPU_CycleLeft) {
+                       CPU_Cycles=cycles;
+               } else {
+                       CPU_Cycles=CPU_CycleLeft;
+               }
+       } else CPU_Cycles=CPU_CycleLeft;
+       CPU_CycleLeft-=CPU_Cycles;
+       if      (PIC_IRQCheck)  PIC_runIRQs();
+       return true;
+}
+
+#if 0
+/* The TIMER Part */
+struct TickerBlock {
+       TIMER_TickHandler handler;
+       TickerBlock * next;
+};
+
+static TickerBlock * firstticker=0;
+
+
+void TIMER_DelTickHandler(TIMER_TickHandler handler) {
+       TickerBlock * ticker=firstticker;
+       TickerBlock * * tick_where=&firstticker;
+       while (ticker) {
+               if (ticker->handler==handler) {
+                       *tick_where=ticker->next;
+                       delete ticker;
+                       return;
+               }
+               tick_where=&ticker->next;
+               ticker=ticker->next;
+       }
+}
+
+void TIMER_AddTickHandler(TIMER_TickHandler handler) {
+       TickerBlock * newticker=new TickerBlock;
+       newticker->next=firstticker;
+       newticker->handler=handler;
+       firstticker=newticker;
+}
+
+void TIMER_AddTick(void) {
+       /* Setup new amount of cycles for PIC */
+       CPU_CycleLeft=CPU_CycleMax;
+       CPU_Cycles=0;
+       PIC_Ticks++;
+       /* Go through the list of scheduled events and lower their index with 1000 */
+       PICEntry * entry=pic_queue.next_entry;
+       while (entry) {
+               entry->index -= 1.0;
+               entry=entry->next;
+       }
+       /* Call our list of ticker handlers */
+       TickerBlock * ticker=firstticker;
+       while (ticker) {
+               TickerBlock * nextticker=ticker->next;
+               ticker->handler();
+               ticker=nextticker;
+       }
+}
+#endif
+
+void x86_pic_write(Bitu port, Bitu val)
+{
+       switch(port)
+       {
+               case 0x20:
+               case 0xa0:
+               write_command(port, val, 1);
+               break;
+               case 0x21:
+               case 0xa1:
+               write_data(port, val, 1);
+               break;
+       }
+}
+Bitu x86_pic_read(Bitu port)
+{
+       switch (port)
+       {
+               case 0x20:
+               case 0xa0:
+               return read_command(port, 1);
+               case 0x21:
+               case 0xa1:
+               return read_data(port, 1);
+               break;
+       }
+       return 0;
+}
+
+class PIC:public Module_base{
+private:
+//     IO_ReadHandleObject ReadHandler[4];
+//     IO_WriteHandleObject WriteHandler[4];
+public:
+       PIC(Section* configuration):Module_base(configuration){
+               /* Setup pic0 and pic1 with initial values like DOS has normally */
+               PIC_IRQCheck=0;
+               PIC_IRQActive=PIC_NOIRQ;
+               PIC_Ticks=0;
+               Bitu i;
+               for (i=0;i<2;i++) {
+                       pics[i].masked=0xff;
+                       pics[i].auto_eoi=false;
+                       pics[i].rotate_on_auto_eoi=false;
+                       pics[i].request_issr=false;
+                       pics[i].special=false;
+                       pics[i].single=false;
+                       pics[i].icw_index=0;
+                       pics[i].icw_words=0;
+               }
+               for (i=0;i<=7;i++) {
+                       irqs[i].active=false;
+                       irqs[i].masked=true;
+                       irqs[i].inservice=false;
+                       irqs[i+8].active=false;
+                       irqs[i+8].masked=true;
+                       irqs[i+8].inservice=false;
+                       irqs[i].vector=0x8+i;
+                       irqs[i+8].vector=0x70+i;        
+               }
+               irqs[0].masked=false;                                   /* Enable system timer */
+               irqs[1].masked=false;                                   /* Enable Keyboard IRQ */
+               irqs[2].masked=false;                                   /* Enable second pic */
+               irqs[8].masked=false;                                   /* Enable RTC IRQ */
+#if 0
+               if (machine==MCH_PCJR) {
+                       /* Enable IRQ6 (replacement for the NMI for PCJr) */
+                       irqs[6].masked=false;
+               }
+               ReadHandler[0].Install(0x20,read_command,IO_MB);
+               ReadHandler[1].Install(0x21,read_data,IO_MB);
+               WriteHandler[0].Install(0x20,write_command,IO_MB);
+               WriteHandler[1].Install(0x21,write_data,IO_MB);
+               ReadHandler[2].Install(0xa0,read_command,IO_MB);
+               ReadHandler[3].Install(0xa1,read_data,IO_MB);
+               WriteHandler[2].Install(0xa0,write_command,IO_MB);
+               WriteHandler[3].Install(0xa1,write_data,IO_MB);
+#endif
+               /* Initialize the pic queue */
+               for (i=0;i<PIC_QUEUESIZE-1;i++) {
+                       pic_queue.entries[i].next=&pic_queue.entries[i+1];
+               }
+               pic_queue.entries[PIC_QUEUESIZE-1].next=0;
+               pic_queue.free_entry=&pic_queue.entries[0];
+               pic_queue.next_entry=0;
+       }
+       ~PIC(){
+       }
+};
+
+static PIC* test;
+
+void PIC_Destroy(Section* sec){
+       delete test;
+}
+
+void PIC_Init(Section* sec) {
+       test = new PIC(sec);
+       sec->AddDestroyFunction(&PIC_Destroy);
+}
diff --git a/dosbox/pic.h b/dosbox/pic.h
new file mode 100644 (file)
index 0000000..8b6e2f4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  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.
+ */
+
+#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);
+
+
+#define PIC_MAXIRQ 15
+#define PIC_NOIRQ 0xFF
+
+extern Bitu PIC_IRQCheck;
+extern Bitu PIC_IRQActive;
+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/dosbox/regs.h b/dosbox/regs.h
new file mode 100644 (file)
index 0000000..13da923
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *  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.
+ */
+
+#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 | FLAG_AC )   
+#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 {
+       Bitu 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/dosbox/setup.h b/dosbox/setup.h
new file mode 100644 (file)
index 0000000..db75ada
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ *  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: setup.h,v 1.41 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#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
+
+
+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) :_string(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);
+       void 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();
+       void set_hex(std::string const& in);
+       void set_int(std::string const&in);
+       void set_bool(std::string const& in);
+       void set_string(std::string const& in);
+       void 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 void 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);
+       //Set interval value to in or default if in is invalid. force always sets the value.
+       void SetVal(Value const& in, bool forced,bool warn=true) {if(forced || CheckValue(in,warn)) value = in; else value = default_value;}
+       virtual ~Property(){ } 
+       virtual const std::vector<Value>& GetValues() const;
+       Value::Etype Get_type(){return default_value.type;}
+
+protected:
+       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;
+       }
+       void SetMinMax(Value const& min,Value const& max) {this->min = min; this->max=max;}
+       void SetValue(std::string const& in);
+       ~Prop_int(){ }
+       virtual bool CheckValue(Value const& in, bool warn);
+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;
+       }
+       void 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;
+       }
+       void 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;
+       }
+       void 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;
+       }
+       void 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;
+       }
+       void 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 void 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;
+       void 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 seperator;
+       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("")),seperator(sep) {
+               default_value = value = "";
+       }
+       Section_prop *GetSection() { return section; }
+       const Section_prop *GetSection() const { return section; }
+       virtual void 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 void SetValue(std::string const& input);
+};
+
+   
+class Section_line: public Section{
+public:
+       Section_line(std::string const& _sectionname):Section(_sectionname){}
+       ~Section_line(){ExecuteDestroy(true);}
+       void 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/dosbox/support.h b/dosbox/support.h
new file mode 100644 (file)
index 0000000..32e1e20
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  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: support.h,v 1.18 2009-05-27 09:15:41 qbix79 Exp $ */
+
+#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);
+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);
+
+#endif