+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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 <string.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[3 * 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;
- int ram_mask;
-} cmos;
-extern int x86_cmos_bank;
-
-Bit8u *x86_cmos_regs(Bit8u *regs)
-{
- if (regs) {
- memcpy(cmos.regs, regs, 3 * 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)
-}
-
-extern void write_log(const char*,...);
-
-void cmos_selreg(Bitu port,Bitu val,Bitu iolen) {
- cmos.reg=val & cmos.ram_mask;
- cmos.nmi=(val & 0x80)>0;
-}
-
-void cmos_writereg(Bitu port,Bitu val,Bitu iolen)
-{
- int reg = cmos.reg;
- if (reg >= 64 && x86_cmos_bank)
- reg += 64;
-
- //write_log("cmos_write %02x (%d) = %02x\n", cmos.reg, x86_cmos_bank, val);
-
- reg &= cmos.ram_mask;
-
- switch (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[reg]=val;
- break;
- case 0x0a: /* Status reg A */
- cmos.regs[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[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[reg]=val & 0x80; /*Bit 7=1:RTC Pown on*/
- break;
- case 0x0f: /* Shutdown status byte */
- cmos.regs[reg]=val;// & 0x7f;
- break;
- default:
- cmos.regs[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));
-
-extern double vblank_hz;
-extern unsigned long int timeframes;
-extern int vpos;
-extern bool x86_turbo_on;
-
-static Bitu cmos_readreg2(Bitu port,Bitu iolen) {
-#if 0
- if (cmos.reg>0x3f) {
- LOG(LOG_BIOS,LOG_ERROR)("CMOS:Read from illegal register %x",cmos.reg);
- return 0xff;
- }
-#endif
- time_t curtime;
- struct tm *loctime;
- int reg = cmos.reg;
- if (reg >= 64 && x86_cmos_bank)
- reg += 64;
- reg &= cmos.ram_mask;
-
- /* Get the current time. */
- curtime = time (NULL);
-
- /* Convert it to local time representation. */
- loctime = localtime (&curtime);
-
- switch (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[reg];
- case 0x0a: /* Status register A */
- if (x86_turbo_on) {
- static bool toggle;
- toggle = !toggle;
- if (toggle) {
- return (cmos.regs[0x0a] & 0x7f) | 0x80;
- } else {
- return (cmos.regs[0x0a] & 0x7f);
- }
- } else {
- if (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;
- case 0x39:
- return 0;
- case 0x3a:
- return 0;
-#endif
-
-
- 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[reg]);
- return cmos.regs[reg];
- default:
- LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X",cmos.reg);
- return cmos.regs[reg];
- }
-}
-
-Bitu cmos_readreg(Bitu port, Bitu iolen)
-{
- Bitu v = cmos_readreg2(port, iolen);
- //write_log("cmos_read %02x (%d) = %02x\n", cmos.reg, x86_cmos_bank, v);
- return v;
-}
-
-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, int ram_mask):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.ram_mask = ram_mask;
- 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 */
-#if 0
- // 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);
-#endif
- }
-};
-
-static CMOS* test;
-
-void CMOS_Destroy(Section* sec){
- delete test;
-}
-
-void CMOS_Init(Section* sec, int ram_mask) {
- test = new CMOS(sec, ram_mask);
- sec->AddDestroyFunction(&CMOS_Destroy,true);
-}
+++ /dev/null
-/*
- * 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) {
-
-}
+++ /dev/null
-{
- 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]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_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;
- }
-}
+++ /dev/null
-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;
-}
-
+++ /dev/null
-#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
-
+++ /dev/null
-/* 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);
-
-}
+++ /dev/null
-/* 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 },
-
-
-
-}
-};
-
-
-
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-{
- 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);
- }
-}
+++ /dev/null
-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
-
+++ /dev/null
-/*
- * 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) {
-
-}
-
+++ /dev/null
-/*
- * 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)
+++ /dev/null
-/*
- * 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;
-
+++ /dev/null
-/*
- * 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;
- }
-
-
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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;
- }
-
-
-
-
+++ /dev/null
-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);
- }
-}
+++ /dev/null
-/*
- * 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"
-
-
+++ /dev/null
-/*
- * 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]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_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(); \
- } \
-
-
+++ /dev/null
-/*
- * 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) {
-
-}
+++ /dev/null
-/*
- * 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 <stddef.h>
-#include "dosbox.h"
-#include "cpu.h"
-//#include "memory.h"
-//#include "debug.h"
-//#include "mapper.h"
-#include "setup.h"
-//#include "programs.h"
-#include "paging.h"
-#include "lazyflags.h"
-#include "support.h"
-
-Bitu DEBUG_EnableDebugger(void);
-extern void GFX_SetTitle(Bit32s cycles ,Bits frameskip,bool paused);
-
-#if 1
-#undef LOG
-#if defined (_MSC_VER)
-#define LOG(X,Y)
-#else
-#define LOG(X,Y) CPU_LOG
-#define CPU_LOG(...)
-#endif
-#endif
-
-CPU_Regs cpu_regs;
-CPUBlock cpu;
-Segments Segs;
-
-Bit32s CPU_Cycles = 0;
-Bit32s CPU_CycleLeft = 3000;
-Bit32s CPU_CycleMax = 3000;
-Bit32s CPU_OldCycleMax = 3000;
-Bit32s CPU_CyclePercUsed = 100;
-Bit32s CPU_CycleLimit = -1;
-Bit32s CPU_CycleUp = 0;
-Bit32s CPU_CycleDown = 0;
-Bit64s CPU_IODelayRemoved = 0;
-CPU_Decoder * cpudecoder;
-bool CPU_CycleAutoAdjust = false;
-bool CPU_SkipCycleAutoAdjust = false;
-Bitu CPU_AutoDetermineMode = 0;
-
-Bitu CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
-
-Bitu CPU_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, int cpumode, int cpuarch):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, cpumode, cpuarch);
- CPU_JMP(false,0,0,0); //Setup the first cpu core
- }
- bool Change_Config(Section* newconfig, int cpumode, int cpuarch){
- 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";
- if (cpumode == 2)
- core = "normal";
- else if (cpumode == 3)
- core = "full";
- else if (cpumode == 4)
- core = "auto";
-
- 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 (cpuarch == 1)
- cputype = "386";
- else if (cpuarch == 2)
- cputype = "386_prefetch";
- else if (cpuarch == 3)
- cputype = "386_slow";
- else if (cpuarch == 4)
- cputype = "486_slow";
- else if (cpuarch == 5)
- cputype = "486_prefetch";
- else if (cpuarch == 6)
- cputype = "pentium_slow";
-
- 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, int cpumode, int cpuarch) {
- test = new CPU(sec, cpumode, cpuarch);
- sec->AddDestroyFunction(&CPU_ShutDown,true);
-}
-//initialize static members
-bool CPU::inited=false;
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
- }
-};
-
-
-extern void write_log(const char*,...);
-extern void vga_ram_put(int board, int offset, uint8_t v);
-extern uint8_t vga_ram_get(int board, int offset);
-extern int x86_vga_board;
-
-
-class VGA_Handler : public PageHandler {
-public:
- VGA_Handler() {
- flags = PFLAG_NOCODE;
- }
- Bitu readb(PhysPt addr) {
- return vga_ram_get(x86_vga_board, addr);
- }
- Bitu readw(PhysPt addr) {
- Bitu v = vga_ram_get(x86_vga_board,addr) << 0;
- v |= vga_ram_get(x86_vga_board, addr + 1) << 8;
- return v;
- }
- Bitu readd(PhysPt addr) {
- Bitu v = readw(addr);
- v |= readw(addr + 2) << 16;
- return v;
- }
- void writeb(PhysPt addr, Bitu val) {
- vga_ram_put(x86_vga_board, addr, val);
- }
- void writew(PhysPt addr, Bitu val) {
- vga_ram_put(x86_vga_board, addr, val);
- vga_ram_put(x86_vga_board, addr + 1, val >> 8);
- return;
- }
- void writed(PhysPt addr, Bitu val) {
- writew(addr, val);
- writew(addr + 2, val >> 16);
- return;
- }
-};
-static VGA_Handler vga_page_handler;
-
-void MEM_SetVGAHandler(void)
-{
- MEM_SetPageHandler(0xa0000 >> 12, (0xc0000 - 0xa0000) >> 12, &vga_page_handler);
-}
-
-
-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_ResetPageHandlerRAM(Bitu phys_page, Bitu pages) {
- for (;pages>0;pages--) {
- memory.phandlers[phys_page]=&ram_page_handler;
- phys_page++;
- }
-}
-
-void MEM_ResetPageHandlerROM(Bitu phys_page, Bitu pages)
-{
- for (; pages>0; pages--) {
- memory.phandlers[phys_page] = &rom_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;
-extern int x86_xrom_start[2], x86_xrom_end[2];
-
-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
-
- // make sure (unused) lfb is out side of our memory range
- memory.lfb.start_page = (128 * 1024 * 1024) / 4096;
-
- 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
- for (int j = 0; j < 2; j++) {
- if (x86_xrom_start[j]) {
- for (i = (x86_xrom_start[j] >> 12); i < (x86_xrom_end[j] >> 12); i++) {
- memory.phandlers[i] = &rom_page_handler;
- }
- }
- }
-
- /* 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);
-}
+++ /dev/null
-#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 C_UNALIGNED_MEMORY
-
-#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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
-}
-
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
+++ /dev/null
-/*
- * 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_keyboard(void);
-
-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_keyboard();
-}
-
-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();
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-#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
+++ /dev/null
-/*
- * 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
-*/
-
-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();
-}
-
-#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
-
-static INLINE Bit8u host_readb(HostPt off) {
- return off[0];
-}
-static INLINE Bit16u host_readw(HostPt off) {
- return off[0] | (off[1] << 8);
-}
-static INLINE Bit32u host_readd(HostPt off) {
- return off[0] | (off[1] << 8) | (off[2] << 16) | (off[3] << 24);
-}
-static INLINE void host_writeb(HostPt off,Bit8u val) {
- 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) {
- bridge_special_addr_check(off);
- *(Bit8u *)(off)=val;
-}
-static INLINE void host_writew(HostPt off,Bit16u val) {
- bridge_special_addr_check(off);
- *(Bit16u *)(off)=val;
-}
-static INLINE void host_writed(HostPt off,Bit32u val) {
- bridge_special_addr_check(off);
- *(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
-
+++ /dev/null
-/*
- * 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[]=
-{
- ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
- ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
- ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
- ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
- ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
- ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
- ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
- ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
-
- ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
- ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
- ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
- ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
- ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
- ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
- ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
- ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
-
- ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
- ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
- ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
- ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
- ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
- ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
- ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
- ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
-
- ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
- ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
- ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
- ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
- ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
- ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
- ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
- ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh
-};
-
-Bit16u * lookupRMregw[]={
- ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
- ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
- ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
- ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
- ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
- ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
- ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
- ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
-
- ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
- ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
- ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
- ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
- ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
- ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
- ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
- ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
-
- ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
- ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
- ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
- ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
- ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
- ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
- ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
- ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
-
- ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
- ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
- ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
- ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
- ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
- ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
- ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
- ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di
-};
-
-Bit32u * lookupRMregd[256]={
- ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
- ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
- ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
- ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
- ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
- ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
- ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
- ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
-
- ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
- ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
- ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
- ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
- ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
- ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
- ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
- ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
-
- ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
- ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
- ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
- ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
- ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
- ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
- ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
- ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
-
- ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
- ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
- ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
- ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
- ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
- ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
- ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
- ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_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,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
- ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_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,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
- ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_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,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
- ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi
-};
-
-
+++ /dev/null
-/*
- * 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];
-
-
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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_ResetPageHandlerRAM(Bitu phys_page, Bitu pages);
-void MEM_ResetPageHandlerROM(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
+++ /dev/null
-/*
- * 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;
-}
-
-/* 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;
- }
-}
-
-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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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: timer.cpp,v 1.49 2009-04-10 09:53:04 c2woody Exp $ */
-
-#include <math.h>
-#include "dosbox.h"
-#include "inout.h"
-#include "pic.h"
-#include "mem.h"
-//#include "mixer.h"
-#include "timer.h"
-#include "setup.h"
-
-static INLINE void BIN2BCD(Bit16u& val) {
- Bit16u temp=val%10 + (((val/10)%10)<<4)+ (((val/100)%10)<<8) + (((val/1000)%10)<<12);
- val=temp;
-}
-
-static INLINE void BCD2BIN(Bit16u& val) {
- Bit16u temp= (val&0x0f) +((val>>4)&0x0f) *10 +((val>>8)&0x0f) *100 +((val>>12)&0x0f) *1000;
- val=temp;
-}
-
-struct PIT_Block {
- Bitu cntr;
- float delay;
- double start;
-
- Bit16u read_latch;
- Bit16u write_latch;
-
- Bit8u mode;
- Bit8u latch_mode;
- Bit8u read_state;
- Bit8u write_state;
-
- bool bcd;
- bool go_read_latch;
- bool new_mode;
- bool counterstatus_set;
- bool counting;
- bool update_count;
-};
-
-static PIT_Block pit[3];
-static bool gate2;
-
-static Bit8u latched_timerstatus;
-// the timer status can not be overwritten until it is read or the timer was
-// reprogrammed.
-static bool latched_timerstatus_locked;
-
-static void PIT0_Event(Bitu /*val*/) {
- PIC_ActivateIRQ(0);
- if (pit[0].mode != 0) {
- pit[0].start += pit[0].delay;
-
- if (GCC_UNLIKELY(pit[0].update_count)) {
- pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr));
- pit[0].update_count=false;
- }
- PIC_AddEvent(PIT0_Event,pit[0].delay);
- }
-}
-
-static bool counter_output(Bitu counter) {
- PIT_Block * p=&pit[counter];
- double index=PIC_FullIndex()-p->start;
- switch (p->mode) {
- case 0:
- if (p->new_mode) return false;
- if (index>p->delay) return true;
- else return false;
- break;
- case 2:
- if (p->new_mode) return true;
- index=fmod(index,(double)p->delay);
- return index>0;
- case 3:
- if (p->new_mode) return true;
- index=fmod(index,(double)p->delay);
- return index*2<p->delay;
- case 4:
- //Only low on terminal count
- // if(fmod(index,(double)p->delay) == 0) return false; //Maybe take one rate tick in consideration
- //Easiest solution is to report always high (Space marines uses this mode)
- return true;
- default:
- LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode);
- return true;
- }
-}
-static void status_latch(Bitu counter) {
- // the timer status can not be overwritten until it is read or the timer was
- // reprogrammed.
- if(!latched_timerstatus_locked) {
- PIT_Block * p=&pit[counter];
- latched_timerstatus=0;
- // Timer Status Word
- // 0: BCD
- // 1-3: Timer mode
- // 4-5: read/load mode
- // 6: "NULL" - this is 0 if "the counter value is in the counter" ;)
- // should rarely be 1 (i.e. on exotic modes)
- // 7: OUT - the logic level on the Timer output pin
- if(p->bcd)latched_timerstatus|=0x1;
- latched_timerstatus|=((p->mode&7)<<1);
- if((p->read_state==0)||(p->read_state==3)) latched_timerstatus|=0x30;
- else if(p->read_state==1) latched_timerstatus|=0x10;
- else if(p->read_state==2) latched_timerstatus|=0x20;
- if(counter_output(counter)) latched_timerstatus|=0x80;
- if(p->new_mode) latched_timerstatus|=0x40;
- // The first thing that is being read from this counter now is the
- // counter status.
- p->counterstatus_set=true;
- latched_timerstatus_locked=true;
- }
-}
-static void counter_latch(Bitu counter) {
- /* Fill the read_latch of the selected counter with current count */
- PIT_Block * p=&pit[counter];
- p->go_read_latch=false;
-
- //If gate2 is disabled don't update the read_latch
- if(counter == 2 && !gate2 && p->mode !=1) return;
-
- double index=PIC_FullIndex()-p->start;
- switch (p->mode) {
- case 4: /* Software Triggered Strobe */
- case 0: /* Interrupt on Terminal Count */
- /* Counter keeps on counting after passing terminal count */
- if (index>p->delay) {
- index-=p->delay;
- if(p->bcd) {
- index = fmod(index,(1000.0/PIT_TICK_RATE)*10000.0);
- p->read_latch = (Bit16u)(9999-index*(PIT_TICK_RATE/1000.0));
- } else {
- index = fmod(index,(1000.0/PIT_TICK_RATE)*(double)0x10000);
- p->read_latch = (Bit16u)(0xffff-index*(PIT_TICK_RATE/1000.0));
- }
- } else {
- p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0));
- }
- break;
- case 1: // countdown
- if(p->counting) {
- if (index>p->delay) { // has timed out
- p->read_latch = 0xffff; //unconfirmed
- } else {
- p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0));
- }
- }
- break;
- case 2: /* Rate Generator */
- index=fmod(index,(double)p->delay);
- p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr);
- break;
- case 3: /* Square Wave Rate Generator */
- index=fmod(index,(double)p->delay);
- index*=2;
- if (index>p->delay) index-=p->delay;
- p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr);
- // In mode 3 it never returns odd numbers LSB (if odd number is written 1 will be
- // subtracted on first clock and then always 2)
- // fixes "Corncob 3D"
- p->read_latch&=0xfffe;
- break;
- default:
- LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter);
- p->read_latch=0xffff;
- break;
- }
-}
-
-
-static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
-//LOG(LOG_PIT,LOG_ERROR)("port %X write:%X state:%X",port,val,pit[port-0x40].write_state);
- Bitu counter=port-0x40;
- PIT_Block * p=&pit[counter];
- if(p->bcd == true) BIN2BCD(p->write_latch);
-
- switch (p->write_state) {
- case 0:
- p->write_latch = p->write_latch | ((val & 0xff) << 8);
- p->write_state = 3;
- break;
- case 3:
- p->write_latch = val & 0xff;
- p->write_state = 0;
- break;
- case 1:
- p->write_latch = val & 0xff;
- break;
- case 2:
- p->write_latch = (val & 0xff) << 8;
- break;
- }
- if (p->bcd==true) BCD2BIN(p->write_latch);
- if (p->write_state != 0) {
- if (p->write_latch == 0) {
- if (p->bcd == false) p->cntr = 0x10000;
- else p->cntr=9999;
- } else p->cntr = p->write_latch;
-
- if ((!p->new_mode) && (p->mode == 2) && (counter == 0)) {
- // In mode 2 writing another value has no direct effect on the count
- // until the old one has run out. This might apply to other modes too.
- // This is not fixed for PIT2 yet!!
- p->update_count=true;
- return;
- }
- p->start=PIC_FullIndex();
- p->delay=(1000.0f/((float)PIT_TICK_RATE/(float)p->cntr));
-
- switch (counter) {
- case 0x00: /* Timer hooked to IRQ 0 */
- if (p->new_mode || p->mode == 0 ) {
- if(p->mode==0) PIC_RemoveEvents(PIT0_Event); // DoWhackaDo demo
- PIC_AddEvent(PIT0_Event,p->delay);
- } else LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer set without new control word");
- LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.4f Hz mode %d",1000.0/p->delay,p->mode);
- break;
- case 0x02: /* Timer hooked to PC-Speaker */
-// LOG(LOG_PIT,"PIT 2 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode);
-// PCSPEAKER_SetCounter(p->cntr,p->mode);
- // HACK. A1060 bios hardware diagnostics reads latch with timer gate 2 disabled
- // and expects original written value.
- if (!gate2)
- p->read_latch = p->write_latch;
- break;
- default:
- LOG(LOG_PIT,LOG_ERROR)("PIT:Illegal timer selected for writing");
- }
- p->new_mode=false;
- }
-}
-
-static Bitu read_latch(Bitu port,Bitu /*iolen*/) {
-//LOG(LOG_PIT,LOG_ERROR)("port read %X",port);
- Bit32u counter=port-0x40;
- Bit8u ret=0;
- if(GCC_UNLIKELY(pit[counter].counterstatus_set)){
- pit[counter].counterstatus_set = false;
- latched_timerstatus_locked = false;
- ret = latched_timerstatus;
- } else {
- if (pit[counter].go_read_latch == true)
- counter_latch(counter);
-
- if( pit[counter].bcd == true) BIN2BCD(pit[counter].read_latch);
-
- switch (pit[counter].read_state) {
- case 0: /* read MSB & return to state 3 */
- ret=(pit[counter].read_latch >> 8) & 0xff;
- pit[counter].read_state = 3;
- pit[counter].go_read_latch = true;
- break;
- case 3: /* read LSB followed by MSB */
- ret = pit[counter].read_latch & 0xff;
- pit[counter].read_state = 0;
- break;
- case 1: /* read LSB */
- ret = pit[counter].read_latch & 0xff;
- pit[counter].go_read_latch = true;
- break;
- case 2: /* read MSB */
- ret = (pit[counter].read_latch >> 8) & 0xff;
- pit[counter].go_read_latch = true;
- break;
- default:
- E_Exit("Timer.cpp: error in readlatch");
- break;
- }
- if( pit[counter].bcd == true) BCD2BIN(pit[counter].read_latch);
- }
- return ret;
-}
-
-static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
-//LOG(LOG_PIT,LOG_ERROR)("port 43 %X",val);
- Bitu latch=(val >> 6) & 0x03;
- switch (latch) {
- case 0:
- case 1:
- case 2:
- if ((val & 0x30) == 0) {
- /* Counter latch command */
- counter_latch(latch);
- } else {
- pit[latch].bcd = (val&1)>0;
- if (val & 1) {
- if(pit[latch].cntr>=9999) pit[latch].cntr=9999;
- }
-
- // Timer is being reprogrammed, unlock the status
- if(pit[latch].counterstatus_set) {
- pit[latch].counterstatus_set=false;
- latched_timerstatus_locked=false;
- }
- pit[latch].update_count = false;
- pit[latch].counting = false;
- pit[latch].read_state = (val >> 4) & 0x03;
- pit[latch].write_state = (val >> 4) & 0x03;
- Bit8u mode = (val >> 1) & 0x07;
- if (mode > 5)
- mode -= 4; //6,7 become 2 and 3
-
- /* Don't set it directly so counter_output uses the old mode */
- /* That's theory. It breaks panic. So set it here again */
- if(!pit[latch].mode) pit[latch].mode = mode;
-
- /* If the line goes from low to up => generate irq.
- * ( BUT needs to stay up until acknowlegded by the cpu!!! therefore: )
- * If the line goes to low => disable irq.
- * Mode 0 starts with a low line. (so always disable irq)
- * Mode 2,3 start with a high line.
- * counter_output tells if the current counter is high or low
- * So actually a mode 2 timer enables and disables irq al the time. (not handled) */
-
- if (latch == 0) {
- PIC_RemoveEvents(PIT0_Event);
- if (!counter_output(0) && mode) {
- PIC_ActivateIRQ(0);
- //Don't raise instantaniously. (Origamo)
- if(CPU_Cycles < 25) CPU_Cycles = 25;
- }
- if(!mode)
- PIC_DeActivateIRQ(0);
- }
- pit[latch].new_mode = true;
- pit[latch].mode = mode; //Set the correct mode (here)
- }
- break;
- case 3:
- if ((val & 0x20)==0) { /* Latch multiple pit counters */
- if (val & 0x02) counter_latch(0);
- if (val & 0x04) counter_latch(1);
- if (val & 0x08) counter_latch(2);
- }
- // status and values can be latched simultaneously
- if ((val & 0x10)==0) { /* Latch status words */
- // but only 1 status can be latched simultaneously
- if (val & 0x02) status_latch(0);
- else if (val & 0x04) status_latch(1);
- else if (val & 0x08) status_latch(2);
- }
- break;
- }
-}
-
-bool TIMER_GetGate2(void)
-{
- if (!gate2) {
- return true;
- }
- return false;
-}
-
-void TIMER_SetGate2(bool in) {
- //No changes if gate doesn't change
- if(gate2 == in) return;
- Bit8u & mode=pit[2].mode;
- switch(mode) {
- case 0:
- if(in) pit[2].start = PIC_FullIndex();
- else {
- //Fill readlatch and store it.
- counter_latch(2);
- pit[2].cntr = pit[2].read_latch;
- }
- break;
- case 1:
- // gate 1 on: reload counter; off: nothing
- if(in) {
- pit[2].counting = true;
- pit[2].start = PIC_FullIndex();
- }
- break;
- case 2:
- case 3:
- //If gate is enabled restart counting. If disable store the current read_latch
- if(in) pit[2].start = PIC_FullIndex();
- else counter_latch(2);
- break;
- case 4:
- case 5:
- LOG(LOG_MISC,LOG_WARN)("unsupported gate 2 mode %x",mode);
- break;
- }
- gate2 = in; //Set it here so the counter_latch above works
-}
-
-void x86_timer_write(Bitu port, Bitu val)
-{
- switch (port)
- {
- case 0x40:
- case 0x41:
- case 0x42:
- write_latch(port, val, 1);
- break;
- case 0x43:
- write_p43(port, val, 1);
- break;
- }
-}
-Bitu x86_timer_read(Bitu port)
-{
- switch (port)
- {
- case 0x40:
- case 0x41:
- case 0x42:
- return read_latch(port, 1);
- break;
- }
- return 0;
-}
-
-class TIMER:public Module_base{
-//private:
-// IO_ReadHandleObject ReadHandler[4];
-// IO_WriteHandleObject WriteHandler[4];
-public:
- TIMER(Section* configuration):Module_base(configuration){
-#if 0
- WriteHandler[0].Install(0x40,write_latch,IO_MB);
- // WriteHandler[1].Install(0x41,write_latch,IO_MB);
- WriteHandler[2].Install(0x42,write_latch,IO_MB);
- WriteHandler[3].Install(0x43,write_p43,IO_MB);
- ReadHandler[0].Install(0x40,read_latch,IO_MB);
- ReadHandler[1].Install(0x41,read_latch,IO_MB);
- ReadHandler[2].Install(0x42,read_latch,IO_MB);
-#endif
- /* Setup Timer 0 */
- pit[0].cntr=0x10000;
- pit[0].write_state = 3;
- pit[0].read_state = 3;
- pit[0].read_latch=0;
- pit[0].write_latch=0;
- pit[0].mode=3;
- pit[0].bcd = false;
- pit[0].go_read_latch = true;
- pit[0].counterstatus_set = false;
- pit[0].update_count = false;
-
- pit[1].bcd = false;
- pit[1].write_state = 1;
- pit[1].read_state = 1;
- pit[1].go_read_latch = true;
- pit[1].cntr = 18;
- pit[1].mode = 2;
- pit[1].write_state = 3;
- pit[1].counterstatus_set = false;
-
- pit[2].read_latch=1320; /* MadTv1 */
- pit[2].write_state = 3; /* Chuck Yeager */
- pit[2].read_state = 3;
- pit[2].mode=3;
- pit[2].bcd=false;
- pit[2].cntr=1320;
- pit[2].go_read_latch=true;
- pit[2].counterstatus_set = false;
- pit[2].counting = false;
-
- pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr));
- pit[1].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[1].cntr));
- pit[2].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[2].cntr));
-
- latched_timerstatus_locked=false;
- gate2 = false;
- PIC_AddEvent(PIT0_Event,pit[0].delay);
- }
- ~TIMER(){
- PIC_RemoveEvents(PIT0_Event);
- }
-};
-static TIMER* test;
-
-void TIMER_Destroy(Section*){
- delete test;
-}
-void TIMER_Init(Section* sec) {
- test = new TIMER(sec);
- sec->AddDestroyFunction(&TIMER_Destroy);
-}
+++ /dev/null
-/*
- * 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_TIMER_H
-#define DOSBOX_TIMER_H
-
-/* underlying clock rate in HZ */
-//#include <SDL.h>
-
-#define PIT_TICK_RATE 1193182
-
-//#define GetTicks() SDL_GetTicks()
-
-typedef void (*TIMER_TickHandler)(void);
-
-/* Register a function that gets called everytime if 1 or more ticks pass */
-void TIMER_AddTickHandler(TIMER_TickHandler handler);
-void TIMER_DelTickHandler(TIMER_TickHandler handler);
-
-/* This will add 1 milliscond to all timers */
-void TIMER_AddTick(void);
-
-#endif
+++ /dev/null
-/*
- Fake86: A portable, open-source 8086 PC emulator.
- Copyright (C)2010-2012 Mike Chambers
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-/* cpu.c: functions to emulate the 8086/V20 CPU in software. the heart of Fake86. */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#define CPU_V20
-static int x86_cpu_v20;
-
-extern void write_log(const char*,...);
-
-
-#define regax 0
-#define regcx 1
-#define regdx 2
-#define regbx 3
-#define regsp 4
-#define regbp 5
-#define regsi 6
-#define regdi 7
-#define reges 0
-#define regcs 1
-#define regss 2
-#define regds 3
-
-#ifdef __BIG_ENDIAN__
-#define regal 1
-#define regah 0
-#define regcl 3
-#define regch 2
-#define regdl 5
-#define regdh 4
-#define regbl 7
-#define regbh 6
-#else
-#define regal 0
-#define regah 1
-#define regcl 2
-#define regch 3
-#define regdl 4
-#define regdh 5
-#define regbl 6
-#define regbh 7
-#endif
-
-union _bytewordregs_ {
- uint16_t wordregs[8];
- uint8_t byteregs[8];
-};
-
-#define StepIP(x) ip += x
-#define getmem8(x, y) read86(segbase(x) + y)
-#define getmem16(x, y) readw86(segbase(x) + y)
-#define putmem8(x, y, z) write86(segbase(x) + y, z)
-#define putmem16(x, y, z) writew86(segbase(x) + y, z)
-#define signext(value) (int16_t)(int8_t)(value)
-#define signext32(value) (int32_t)(int16_t)(value)
-#define getreg16(regid) regs.wordregs[regid]
-#define getreg8(regid) regs.byteregs[byteregtable[regid]]
-#define putreg16(regid, writeval) regs.wordregs[regid] = writeval
-#define putreg8(regid, writeval) regs.byteregs[byteregtable[regid]] = writeval
-#define getsegreg(regid) segregs[regid]
-#define putsegreg(regid, writeval) segregs[regid] = writeval
-#define segbase(x) ((uint32_t) x << 4)
-
-#if 0
-#include "config.h"
-#include <stdint.h>
-#include <stdio.h>
-#include "cpu.h"
-#include "i8259.h"
-#include "i8253.h"
-
-extern struct i8253_s i8253;
-
-extern struct structpic i8259;
-#endif
-
-uint64_t curtimer, lasttimer, timerfreq;
-
-static uint8_t byteregtable[8] = { regal, regcl, regdl, regbl, regah, regch, regdh, regbh };
-
-static const uint8_t parity[0x100] = {
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
-};
-
-#if 0
-uint8_t RAM[0x100000], readonly[0x100000];
-#endif
-static uint8_t opcode, segoverride, reptype, bootdrive = 0, hdcount = 0;
-static uint16_t segregs[4], savecs, saveip, ip, useseg, oldsp;
-static uint8_t tempcf, oldcf, cf, pf, af, zf, sf, tf, ifl, df, of, mode, reg, rm;
-static uint16_t oper1, oper2, res16, disp16, temp16, dummy, stacksize, frametemp;
-static uint8_t oper1b, oper2b, res8, disp8, temp8, nestlev, addrbyte;
-static uint32_t temp1, temp2, temp3, temp4, temp5, temp32, tempaddr32, ea;
-static int32_t result;
-static uint64_t totalexec;
-
-#if 0
-extern uint16_t VGA_SC[0x100], VGA_CRTC[0x100], VGA_ATTR[0x100], VGA_GC[0x100];
-extern uint8_t updatedscreen;
-#endif
-
-static union _bytewordregs_ regs;
-
-#if 0
-uint8_t portram[0x10000];
-uint8_t running = 0, debugmode, showcsip, verbose;
-uint8_t ethif;
-#endif
-static int verbose = 1;
-static int running = 1;
-
-#if 0
-extern uint8_t vidmode;
-extern uint8_t verbose;
-
-extern void vidinterrupt();
-
-extern uint8_t readVGA (uint32_t addr32);
-#endif
-
-void intcall86 (uint8_t intnum);
-
-#define makeflagsword() \
- ( \
- 2 | (uint16_t) cf | ((uint16_t) pf << 2) | ((uint16_t) af << 4) | ((uint16_t) zf << 6) | ((uint16_t) sf << 7) | \
- ((uint16_t) tf << 8) | ((uint16_t) ifl << 9) | ((uint16_t) df << 10) | ((uint16_t) of << 11) \
- )
-
-#define decodeflagsword(x) { \
- temp16 = x; \
- cf = temp16 & 1; \
- pf = (temp16 >> 2) & 1; \
- af = (temp16 >> 4) & 1; \
- zf = (temp16 >> 6) & 1; \
- sf = (temp16 >> 7) & 1; \
- tf = (temp16 >> 8) & 1; \
- ifl = (temp16 >> 9) & 1; \
- df = (temp16 >> 10) & 1; \
- of = (temp16 >> 11) & 1; \
- }
-
-#if 0
-extern void writeVGA (uint32_t addr32, uint8_t value);
-#endif
-extern void portout (uint16_t portnum, uint8_t value);
-extern void portout16 (uint16_t portnum, uint16_t value);
-extern uint8_t portin (uint16_t portnum);
-extern uint16_t portin16 (uint16_t portnum);
-
-void write86(uint32_t addr32, uint8_t value);
-void writew86(uint32_t addr32, uint16_t value);
-uint8_t read86(uint32_t addr32);
-uint16_t readw86(uint32_t addr32);
-
-void flag_szp8 (uint8_t value) {
- if (!value) {
- zf = 1;
- }
- else {
- zf = 0; /* set or clear zero flag */
- }
-
- if (value & 0x80) {
- sf = 1;
- }
- else {
- sf = 0; /* set or clear sign flag */
- }
-
- pf = parity[value]; /* retrieve parity state from lookup table */
-}
-
-void flag_szp16 (uint16_t value) {
- if (!value) {
- zf = 1;
- }
- else {
- zf = 0; /* set or clear zero flag */
- }
-
- if (value & 0x8000) {
- sf = 1;
- }
- else {
- sf = 0; /* set or clear sign flag */
- }
-
- pf = parity[value & 255]; /* retrieve parity state from lookup table */
-}
-
-void flag_log8 (uint8_t value) {
- flag_szp8 (value);
- cf = 0;
- of = 0; /* bitwise logic ops always clear carry and overflow */
-}
-
-void flag_log16 (uint16_t value) {
- flag_szp16 (value);
- cf = 0;
- of = 0; /* bitwise logic ops always clear carry and overflow */
-}
-
-void flag_adc8 (uint8_t v1, uint8_t v2, uint8_t v3) {
-
- /* v1 = destination operand, v2 = source operand, v3 = carry flag */
- uint16_t dst;
-
- dst = (uint16_t) v1 + (uint16_t) v2 + (uint16_t) v3;
- flag_szp8 ( (uint8_t) dst);
- if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) {
- of = 1;
- }
- else {
- of = 0; /* set or clear overflow flag */
- }
-
- if (dst & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0; /* set or clear carry flag */
- }
-
- if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) {
- af = 1;
- }
- else {
- af = 0; /* set or clear auxilliary flag */
- }
-}
-
-void flag_adc16 (uint16_t v1, uint16_t v2, uint16_t v3) {
-
- uint32_t dst;
-
- dst = (uint32_t) v1 + (uint32_t) v2 + (uint32_t) v3;
- flag_szp16 ( (uint16_t) dst);
- if ( ( ( (dst ^ v1) & (dst ^ v2) ) & 0x8000) == 0x8000) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if (dst & 0xFFFF0000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_add8 (uint8_t v1, uint8_t v2) {
- /* v1 = destination operand, v2 = source operand */
- uint16_t dst;
-
- dst = (uint16_t) v1 + (uint16_t) v2;
- flag_szp8 ( (uint8_t) dst);
- if (dst & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_add16 (uint16_t v1, uint16_t v2) {
- /* v1 = destination operand, v2 = source operand */
- uint32_t dst;
-
- dst = (uint32_t) v1 + (uint32_t) v2;
- flag_szp16 ( (uint16_t) dst);
- if (dst & 0xFFFF0000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( ( (dst ^ v1) & (dst ^ v2) & 0x8000) == 0x8000) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_sbb8 (uint8_t v1, uint8_t v2, uint8_t v3) {
-
- /* v1 = destination operand, v2 = source operand, v3 = carry flag */
- uint16_t dst;
-
- v2 += v3;
- dst = (uint16_t) v1 - (uint16_t) v2;
- flag_szp8 ( (uint8_t) dst);
- if (dst & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( (dst ^ v1) & (v1 ^ v2) & 0x80) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( (v1 ^ v2 ^ dst) & 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_sbb16 (uint16_t v1, uint16_t v2, uint16_t v3) {
-
- /* v1 = destination operand, v2 = source operand, v3 = carry flag */
- uint32_t dst;
-
- v2 += v3;
- dst = (uint32_t) v1 - (uint32_t) v2;
- flag_szp16 ( (uint16_t) dst);
- if (dst & 0xFFFF0000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( (v1 ^ v2 ^ dst) & 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_sub8 (uint8_t v1, uint8_t v2) {
-
- /* v1 = destination operand, v2 = source operand */
- uint16_t dst;
-
- dst = (uint16_t) v1 - (uint16_t) v2;
- flag_szp8 ( (uint8_t) dst);
- if (dst & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( (dst ^ v1) & (v1 ^ v2) & 0x80) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( (v1 ^ v2 ^ dst) & 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void flag_sub16 (uint16_t v1, uint16_t v2) {
-
- /* v1 = destination operand, v2 = source operand */
- uint32_t dst;
-
- dst = (uint32_t) v1 - (uint32_t) v2;
- flag_szp16 ( (uint16_t) dst);
- if (dst & 0xFFFF0000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- if ( (v1 ^ v2 ^ dst) & 0x10) {
- af = 1;
- }
- else {
- af = 0;
- }
-}
-
-void op_adc8() {
- res8 = oper1b + oper2b + cf;
- flag_adc8 (oper1b, oper2b, cf);
-}
-
-void op_adc16() {
- res16 = oper1 + oper2 + cf;
- flag_adc16 (oper1, oper2, cf);
-}
-
-void op_add8() {
- res8 = oper1b + oper2b;
- flag_add8 (oper1b, oper2b);
-}
-
-void op_add16() {
- res16 = oper1 + oper2;
- flag_add16 (oper1, oper2);
-}
-
-void op_and8() {
- res8 = oper1b & oper2b;
- flag_log8 (res8);
-}
-
-void op_and16() {
- res16 = oper1 & oper2;
- flag_log16 (res16);
-}
-
-void op_or8() {
- res8 = oper1b | oper2b;
- flag_log8 (res8);
-}
-
-void op_or16() {
- res16 = oper1 | oper2;
- flag_log16 (res16);
-}
-
-void op_xor8() {
- res8 = oper1b ^ oper2b;
- flag_log8 (res8);
-}
-
-void op_xor16() {
- res16 = oper1 ^ oper2;
- flag_log16 (res16);
-}
-
-void op_sub8() {
- res8 = oper1b - oper2b;
- flag_sub8 (oper1b, oper2b);
-}
-
-void op_sub16() {
- res16 = oper1 - oper2;
- flag_sub16 (oper1, oper2);
-}
-
-void op_sbb8() {
- res8 = oper1b - (oper2b + cf);
- flag_sbb8 (oper1b, oper2b, cf);
-}
-
-void op_sbb16() {
- res16 = oper1 - (oper2 + cf);
- flag_sbb16 (oper1, oper2, cf);
-}
-
-#define modregrm() { \
- addrbyte = getmem8(segregs[regcs], ip); \
- StepIP(1); \
- mode = addrbyte >> 6; \
- reg = (addrbyte >> 3) & 7; \
- rm = addrbyte & 7; \
- switch(mode) \
- { \
- case 0: \
- if(rm == 6) { \
- disp16 = getmem16(segregs[regcs], ip); \
- StepIP(2); \
- } \
- if(((rm == 2) || (rm == 3)) && !segoverride) { \
- useseg = segregs[regss]; \
- } \
- break; \
- \
- case 1: \
- disp16 = signext(getmem8(segregs[regcs], ip)); \
- StepIP(1); \
- if(((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) { \
- useseg = segregs[regss]; \
- } \
- break; \
- \
- case 2: \
- disp16 = getmem16(segregs[regcs], ip); \
- StepIP(2); \
- if(((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) { \
- useseg = segregs[regss]; \
- } \
- break; \
- \
- default: \
- disp8 = 0; \
- disp16 = 0; \
- } \
- }
-
-void getea (uint8_t rmval) {
- uint32_t tempea;
-
- tempea = 0;
- switch (mode) {
- case 0:
- switch (rmval) {
- case 0:
- tempea = regs.wordregs[regbx] + regs.wordregs[regsi];
- break;
- case 1:
- tempea = regs.wordregs[regbx] + regs.wordregs[regdi];
- break;
- case 2:
- tempea = regs.wordregs[regbp] + regs.wordregs[regsi];
- break;
- case 3:
- tempea = regs.wordregs[regbp] + regs.wordregs[regdi];
- break;
- case 4:
- tempea = regs.wordregs[regsi];
- break;
- case 5:
- tempea = regs.wordregs[regdi];
- break;
- case 6:
- tempea = disp16;
- break;
- case 7:
- tempea = regs.wordregs[regbx];
- break;
- }
- break;
-
- case 1:
- case 2:
- switch (rmval) {
- case 0:
- tempea = regs.wordregs[regbx] + regs.wordregs[regsi] + disp16;
- break;
- case 1:
- tempea = regs.wordregs[regbx] + regs.wordregs[regdi] + disp16;
- break;
- case 2:
- tempea = regs.wordregs[regbp] + regs.wordregs[regsi] + disp16;
- break;
- case 3:
- tempea = regs.wordregs[regbp] + regs.wordregs[regdi] + disp16;
- break;
- case 4:
- tempea = regs.wordregs[regsi] + disp16;
- break;
- case 5:
- tempea = regs.wordregs[regdi] + disp16;
- break;
- case 6:
- tempea = regs.wordregs[regbp] + disp16;
- break;
- case 7:
- tempea = regs.wordregs[regbx] + disp16;
- break;
- }
- break;
- }
-
- ea = (tempea & 0xFFFF) + (useseg << 4);
-}
-
-void push (uint16_t pushval) {
- putreg16 (regsp, getreg16 (regsp) - 2);
- putmem16 (segregs[regss], getreg16 (regsp), pushval);
-}
-
-uint16_t pop() {
-
- uint16_t tempval;
-
- tempval = getmem16 (segregs[regss], getreg16 (regsp) );
- putreg16 (regsp, getreg16 (regsp) + 2);
- return tempval;
-}
-
-void reset86(int v20) {
- segregs[regcs] = 0xFFFF;
- ip = 0x0000;
- x86_cpu_v20 = v20;
- //regs.wordregs[regsp] = 0xFFFE;
-}
-
-uint16_t readrm16 (uint8_t rmval) {
- if (mode < 3) {
- getea (rmval);
- return read86 (ea) | ( (uint16_t) read86 (ea + 1) << 8);
- }
- else {
- return getreg16 (rmval);
- }
-}
-
-uint8_t readrm8 (uint8_t rmval) {
- if (mode < 3) {
- getea (rmval);
- return read86 (ea);
- }
- else {
- return getreg8 (rmval);
- }
-}
-
-void writerm16 (uint8_t rmval, uint16_t value) {
- if (mode < 3) {
- getea (rmval);
- write86 (ea, value & 0xFF);
- write86 (ea + 1, value >> 8);
- }
- else {
- putreg16 (rmval, value);
- }
-}
-
-void writerm8 (uint8_t rmval, uint8_t value) {
- if (mode < 3) {
- getea (rmval);
- write86 (ea, value);
- }
- else {
- putreg8 (rmval, value);
- }
-}
-
-uint8_t op_grp2_8 (uint8_t cnt) {
-
- uint16_t s;
- uint16_t shift;
- uint16_t oldcf;
- uint16_t msb;
-
- s = oper1b;
- oldcf = cf;
- if (x86_cpu_v20)
- cnt &= 0x1F;
- switch (reg) {
- case 0: /* ROL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- if (s & 0x80) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = s << 1;
- s = s | cf;
- }
-
- if (cnt == 1) {
- of = cf ^ ( (s >> 7) & 1);
- }
- break;
-
- case 1: /* ROR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- cf = s & 1;
- s = (s >> 1) | (cf << 7);
- }
-
- if (cnt == 1) {
- of = (s >> 7) ^ ( (s >> 6) & 1);
- }
- break;
-
- case 2: /* RCL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- oldcf = cf;
- if (s & 0x80) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = s << 1;
- s = s | oldcf;
- }
-
- if (cnt == 1) {
- of = cf ^ ( (s >> 7) & 1);
- }
- break;
-
- case 3: /* RCR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- oldcf = cf;
- cf = s & 1;
- s = (s >> 1) | (oldcf << 7);
- }
-
- if (cnt == 1) {
- of = (s >> 7) ^ ( (s >> 6) & 1);
- }
- break;
-
- case 4:
- case 6: /* SHL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- if (s & 0x80) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = (s << 1) & 0xFF;
- }
-
- if ( (cnt == 1) && (cf == (s >> 7) ) ) {
- of = 0;
- }
- else {
- of = 1;
- }
-
- flag_szp8 ( (uint8_t) s);
- break;
-
- case 5: /* SHR r/m8 */
- if ( (cnt == 1) && (s & 0x80) ) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- for (shift = 1; shift <= cnt; shift++) {
- cf = s & 1;
- s = s >> 1;
- }
-
- flag_szp8 ( (uint8_t) s);
- break;
-
- case 7: /* SAR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- msb = s & 0x80;
- cf = s & 1;
- s = (s >> 1) | msb;
- }
-
- of = 0;
- flag_szp8 ( (uint8_t) s);
- break;
- }
-
- return s & 0xFF;
-}
-
-uint16_t op_grp2_16 (uint8_t cnt) {
-
- uint32_t s;
- uint32_t shift;
- uint32_t oldcf;
- uint32_t msb;
-
- s = oper1;
- oldcf = cf;
- if (x86_cpu_v20)
- cnt &= 0x1F;
- switch (reg) {
- case 0: /* ROL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- if (s & 0x8000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = s << 1;
- s = s | cf;
- }
-
- if (cnt == 1) {
- of = cf ^ ( (s >> 15) & 1);
- }
- break;
-
- case 1: /* ROR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- cf = s & 1;
- s = (s >> 1) | (cf << 15);
- }
-
- if (cnt == 1) {
- of = (s >> 15) ^ ( (s >> 14) & 1);
- }
- break;
-
- case 2: /* RCL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- oldcf = cf;
- if (s & 0x8000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = s << 1;
- s = s | oldcf;
- }
-
- if (cnt == 1) {
- of = cf ^ ( (s >> 15) & 1);
- }
- break;
-
- case 3: /* RCR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- oldcf = cf;
- cf = s & 1;
- s = (s >> 1) | (oldcf << 15);
- }
-
- if (cnt == 1) {
- of = (s >> 15) ^ ( (s >> 14) & 1);
- }
- break;
-
- case 4:
- case 6: /* SHL r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- if (s & 0x8000) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- s = (s << 1) & 0xFFFF;
- }
-
- if ( (cnt == 1) && (cf == (s >> 15) ) ) {
- of = 0;
- }
- else {
- of = 1;
- }
-
- flag_szp16 ( (uint16_t) s);
- break;
-
- case 5: /* SHR r/m8 */
- if ( (cnt == 1) && (s & 0x8000) ) {
- of = 1;
- }
- else {
- of = 0;
- }
-
- for (shift = 1; shift <= cnt; shift++) {
- cf = s & 1;
- s = s >> 1;
- }
-
- flag_szp16 ( (uint16_t) s);
- break;
-
- case 7: /* SAR r/m8 */
- for (shift = 1; shift <= cnt; shift++) {
- msb = s & 0x8000;
- cf = s & 1;
- s = (s >> 1) | msb;
- }
-
- of = 0;
- flag_szp16 ( (uint16_t) s);
- break;
- }
-
- return (uint16_t) s & 0xFFFF;
-}
-
-void op_div8 (uint16_t valdiv, uint8_t divisor) {
- if (divisor == 0) {
- intcall86 (0);
- return;
- }
-
- if ( (valdiv / (uint16_t) divisor) > 0xFF) {
- intcall86 (0);
- return;
- }
-
- regs.byteregs[regah] = valdiv % (uint16_t) divisor;
- regs.byteregs[regal] = valdiv / (uint16_t) divisor;
-}
-
-void op_idiv8 (uint16_t valdiv, uint8_t divisor) {
-
- uint16_t s1;
- uint16_t s2;
- uint16_t d1;
- uint16_t d2;
- int sign;
-
- if (divisor == 0) {
- intcall86 (0);
- return;
- }
-
- s1 = valdiv;
- s2 = divisor;
- sign = ( ( (s1 ^ s2) & 0x8000) != 0);
- s1 = (s1 < 0x8000) ? s1 : ( (~s1 + 1) & 0xffff);
- s2 = (s2 < 0x8000) ? s2 : ( (~s2 + 1) & 0xffff);
- d1 = s1 / s2;
- d2 = s1 % s2;
- if (d1 & 0xFF00) {
- intcall86 (0);
- return;
- }
-
- if (sign) {
- d1 = (~d1 + 1) & 0xff;
- d2 = (~d2 + 1) & 0xff;
- }
-
- regs.byteregs[regah] = (uint8_t) d2;
- regs.byteregs[regal] = (uint8_t) d1;
-}
-
-void op_grp3_8() {
- oper1 = signext (oper1b);
- oper2 = signext (oper2b);
- switch (reg) {
- case 0:
- case 1: /* TEST */
- flag_log8 (oper1b & getmem8 (segregs[regcs], ip) );
- StepIP (1);
- break;
-
- case 2: /* NOT */
- res8 = ~oper1b;
- break;
-
- case 3: /* NEG */
- res8 = (~oper1b) + 1;
- flag_sub8 (0, oper1b);
- if (res8 == 0) {
- cf = 0;
- }
- else {
- cf = 1;
- }
- break;
-
- case 4: /* MUL */
- temp1 = (uint32_t) oper1b * (uint32_t) regs.byteregs[regal];
- putreg16 (regax, temp1 & 0xFFFF);
- flag_szp8 ( (uint8_t) temp1);
- if (regs.byteregs[regah]) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
-
- if (!x86_cpu_v20)
- zf = 0;
- break;
-
- case 5: /* IMUL */
- oper1 = signext (oper1b);
- temp1 = signext (regs.byteregs[regal]);
- temp2 = oper1;
- if ( (temp1 & 0x80) == 0x80) {
- temp1 = temp1 | 0xFFFFFF00;
- }
-
- if ( (temp2 & 0x80) == 0x80) {
- temp2 = temp2 | 0xFFFFFF00;
- }
-
- temp3 = (temp1 * temp2) & 0xFFFF;
- putreg16 (regax, temp3 & 0xFFFF);
- if (regs.byteregs[regah]) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
- if (!x86_cpu_v20)
- zf = 0;
- break;
-
- case 6: /* DIV */
- op_div8 (getreg16 (regax), oper1b);
- break;
-
- case 7: /* IDIV */
- op_idiv8 (getreg16 (regax), oper1b);
- break;
- }
-}
-
-void op_div16 (uint32_t valdiv, uint16_t divisor) {
- if (divisor == 0) {
- intcall86 (0);
- return;
- }
-
- if ( (valdiv / (uint32_t) divisor) > 0xFFFF) {
- intcall86 (0);
- return;
- }
-
- putreg16 (regdx, valdiv % (uint32_t) divisor);
- putreg16 (regax, valdiv / (uint32_t) divisor);
-}
-
-void op_idiv16 (uint32_t valdiv, uint16_t divisor) {
-
- uint32_t d1;
- uint32_t d2;
- uint32_t s1;
- uint32_t s2;
- int sign;
-
- if (divisor == 0) {
- intcall86 (0);
- return;
- }
-
- s1 = valdiv;
- s2 = divisor;
- s2 = (s2 & 0x8000) ? (s2 | 0xffff0000) : s2;
- sign = ( ( (s1 ^ s2) & 0x80000000) != 0);
- s1 = (s1 < 0x80000000) ? s1 : ( (~s1 + 1) & 0xffffffff);
- s2 = (s2 < 0x80000000) ? s2 : ( (~s2 + 1) & 0xffffffff);
- d1 = s1 / s2;
- d2 = s1 % s2;
- if (d1 & 0xFFFF0000) {
- intcall86 (0);
- return;
- }
-
- if (sign) {
- d1 = (~d1 + 1) & 0xffff;
- d2 = (~d2 + 1) & 0xffff;
- }
-
- putreg16 (regax, d1);
- putreg16 (regdx, d2);
-}
-
-void op_grp3_16() {
- switch (reg) {
- case 0:
- case 1: /* TEST */
- flag_log16 (oper1 & getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 2: /* NOT */
- res16 = ~oper1;
- break;
-
- case 3: /* NEG */
- res16 = (~oper1) + 1;
- flag_sub16 (0, oper1);
- if (res16) {
- cf = 1;
- }
- else {
- cf = 0;
- }
- break;
-
- case 4: /* MUL */
- temp1 = (uint32_t) oper1 * (uint32_t) getreg16 (regax);
- putreg16 (regax, temp1 & 0xFFFF);
- putreg16 (regdx, temp1 >> 16);
- flag_szp16 ( (uint16_t) temp1);
- if (getreg16 (regdx) ) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
- if (!x86_cpu_v20)
- zf = 0;
- break;
-
- case 5: /* IMUL */
- temp1 = getreg16 (regax);
- temp2 = oper1;
- if (temp1 & 0x8000) {
- temp1 |= 0xFFFF0000;
- }
-
- if (temp2 & 0x8000) {
- temp2 |= 0xFFFF0000;
- }
-
- temp3 = temp1 * temp2;
- putreg16 (regax, temp3 & 0xFFFF); /* into register ax */
- putreg16 (regdx, temp3 >> 16); /* into register dx */
- if (getreg16 (regdx) ) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
- if (!x86_cpu_v20)
- zf = 0;
- break;
-
- case 6: /* DIV */
- op_div16 ( ( (uint32_t) getreg16 (regdx) << 16) + getreg16 (regax), oper1);
- break;
-
- case 7: /* DIV */
- op_idiv16 ( ( (uint32_t) getreg16 (regdx) << 16) + getreg16 (regax), oper1);
- break;
- }
-}
-
-void op_grp5() {
- switch (reg) {
- case 0: /* INC Ev */
- oper2 = 1;
- tempcf = cf;
- op_add16();
- cf = tempcf;
- writerm16 (rm, res16);
- break;
-
- case 1: /* DEC Ev */
- oper2 = 1;
- tempcf = cf;
- op_sub16();
- cf = tempcf;
- writerm16 (rm, res16);
- break;
-
- case 2: /* CALL Ev */
- push (ip);
- ip = oper1;
- break;
-
- case 3: /* CALL Mp */
- push (segregs[regcs]);
- push (ip);
- getea (rm);
- ip = (uint16_t) read86 (ea) + (uint16_t) read86 (ea + 1) * 256;
- segregs[regcs] = (uint16_t) read86 (ea + 2) + (uint16_t) read86 (ea + 3) * 256;
- break;
-
- case 4: /* JMP Ev */
- ip = oper1;
- break;
-
- case 5: /* JMP Mp */
- getea (rm);
- ip = (uint16_t) read86 (ea) + (uint16_t) read86 (ea + 1) * 256;
- segregs[regcs] = (uint16_t) read86 (ea + 2) + (uint16_t) read86 (ea + 3) * 256;
- break;
-
- case 6: /* PUSH Ev */
- push (oper1);
- break;
- }
-}
-
-#if 0
-uint8_t dolog = 0, didintr = 0;
-FILE *logout;
-uint8_t printops = 0;
-#endif
-
-#ifdef NETWORKING_ENABLED
-extern void nethandler();
-#endif
-#if 0
-extern void diskhandler();
-extern void readdisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount);
-#endif
-
-void intcall86(uint8_t intnum)
-{
-#if 0
- static uint16_t lastint10ax;
- uint16_t oldregax;
-
- didintr = 1;
-
- if (intnum == 0x19) didbootstrap = 1;
-
- switch (intnum) {
- case 0x10:
- updatedscreen = 1;
- if ((regs.byteregs[regah] == 0x00) || (regs.byteregs[regah] == 0x10)) {
- oldregax = regs.wordregs[regax];
- vidinterrupt();
- regs.wordregs[regax] = oldregax;
- if (regs.byteregs[regah] == 0x10) return;
- if (vidmode == 9) return;
- }
- if ((regs.byteregs[regah] == 0x1A) && (lastint10ax != 0x0100)) { //the 0x0100 is a cheap hack to make it not do this if DOS EDIT/QBASIC
- regs.byteregs[regal] = 0x1A;
- regs.byteregs[regbl] = 0x8;
- return;
- }
- lastint10ax = regs.wordregs[regax];
- break;
-#ifndef DISK_CONTROLLER_ATA
- case 0x19: //bootstrap
- if (bootdrive<255) { //read first sector of boot drive into 07C0:0000 and execute it
- regs.byteregs[regdl] = bootdrive;
- readdisk(regs.byteregs[regdl], 0x07C0, 0x0000, 0, 1, 0, 1);
- segregs[regcs] = 0x0000;
- ip = 0x7C00;
- } else {
- segregs[regcs] = 0xF600; //start ROM BASIC at bootstrap if requested
- ip = 0x0000;
- }
- return;
-
- case 0x13:
- case 0xFD:
- diskhandler();
- return;
-#endif
-#ifdef NETWORKING_OLDCARD
- case 0xFC:
-#ifdef NETWORKING_ENABLED
- nethandler();
-#endif
- return;
-#endif
- }
-#endif
-
- push(makeflagsword());
- push(segregs[regcs]);
- push(ip);
- segregs[regcs] = getmem16(0, (uint16_t)intnum * 4 + 2);
- ip = getmem16(0, (uint16_t)intnum * 4);
- ifl = 0;
- tf = 0;
-}
-
-
-#if defined(NETWORKING_ENABLED)
-extern struct netstruct {
- uint8_t enabled;
- uint8_t canrecv;
- uint16_t pktlen;
-} net;
-#endif
-#if 0
-uint64_t frametimer = 0, didwhen = 0, didticks = 0;
-uint32_t makeupticks = 0;
-extern float timercomp;
-uint64_t timerticks = 0, realticks = 0;
-#endif
-uint64_t lastcountertimer = 0, counterticks = 10000;
-//extern uint8_t nextintr();
-//extern void timing();
-
-extern void check_x86_irq(void);
-
-void exec86 (uint32_t execloops) {
-
- uint32_t loopcount;
- uint8_t docontinue;
- static uint16_t firstip;
- static uint16_t trap_toggle = 0;
-
- counterticks = (uint64_t) ( (double) timerfreq / (double) 65536.0);
-
- for (loopcount = 0; loopcount < execloops; loopcount++) {
-
- //if ( (totalexec & 31) == 0) timing();
-
- if (trap_toggle) {
- intcall86 (1);
- }
-
- if (tf) {
- trap_toggle = 1;
- }
- else {
- trap_toggle = 0;
- }
-
- if (!trap_toggle && ifl)
- check_x86_irq();
-
- reptype = 0;
- segoverride = 0;
- useseg = segregs[regds];
- docontinue = 0;
- firstip = ip;
-
-#if 0
- if ( (segregs[regcs] == 0xF000) && (ip == 0xE066) ) didbootstrap = 0; //detect if we hit the BIOS entry point to clear didbootstrap because we've rebooted
-#endif
-
- while (!docontinue) {
- segregs[regcs] = segregs[regcs] & 0xFFFF;
- ip = ip & 0xFFFF;
- savecs = segregs[regcs];
- saveip = ip;
- opcode = getmem8 (segregs[regcs], ip);
- StepIP (1);
-
- switch (opcode) {
- /* segment prefix check */
- case 0x2E: /* segment segregs[regcs] */
- useseg = segregs[regcs];
- segoverride = 1;
- break;
-
- case 0x3E: /* segment segregs[regds] */
- useseg = segregs[regds];
- segoverride = 1;
- break;
-
- case 0x26: /* segment segregs[reges] */
- useseg = segregs[reges];
- segoverride = 1;
- break;
-
- case 0x36: /* segment segregs[regss] */
- useseg = segregs[regss];
- segoverride = 1;
- break;
-
- /* repetition prefix check */
- case 0xF3: /* REP/REPE/REPZ */
- reptype = 1;
- break;
-
- case 0xF2: /* REPNE/REPNZ */
- reptype = 2;
- break;
-
- default:
- docontinue = 1;
- break;
- }
- }
-
- totalexec++;
-
- /*
- * if (printops == 1) { printf("%04X:%04X - %s\n", savecs, saveip, oplist[opcode]);
- * }
- */
- switch (opcode) {
- case 0x0: /* 00 ADD Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_add8();
- writerm8 (rm, res8);
- break;
-
- case 0x1: /* 01 ADD Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_add16();
- writerm16 (rm, res16);
- break;
-
- case 0x2: /* 02 ADD Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_add8();
- putreg8 (reg, res8);
- break;
-
- case 0x3: /* 03 ADD Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_add16();
- putreg16 (reg, res16);
- break;
-
- case 0x4: /* 04 ADD regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_add8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x5: /* 05 ADD eAX Iv */
- oper1 = (getreg16 (regax) );
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_add16();
- putreg16 (regax, res16);
- break;
-
- case 0x6: /* 06 PUSH segregs[reges] */
- push (segregs[reges]);
- break;
-
- case 0x7: /* 07 POP segregs[reges] */
- segregs[reges] = pop();
- break;
-
- case 0x8: /* 08 OR Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_or8();
- writerm8 (rm, res8);
- break;
-
- case 0x9: /* 09 OR Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_or16();
- writerm16 (rm, res16);
- break;
-
- case 0xA: /* 0A OR Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_or8();
- putreg8 (reg, res8);
- break;
-
- case 0xB: /* 0B OR Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_or16();
- if ( (oper1 == 0xF802) && (oper2 == 0xF802) ) {
- sf = 0; /* cheap hack to make Wolf 3D think we're a 286 so it plays */
- }
-
- putreg16 (reg, res16);
- break;
-
- case 0xC: /* 0C OR regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_or8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0xD: /* 0D OR eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_or16();
- putreg16 (regax, res16);
- break;
-
- case 0xE: /* 0E PUSH segregs[regcs] */
- push (segregs[regcs]);
- break;
-
- case 0xF: //0F POP CS
- if (!x86_cpu_v20)
- segregs[regcs] = pop();
- break;
-
- case 0x10: /* 10 ADC Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_adc8();
- writerm8 (rm, res8);
- break;
-
- case 0x11: /* 11 ADC Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_adc16();
- writerm16 (rm, res16);
- break;
-
- case 0x12: /* 12 ADC Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_adc8();
- putreg8 (reg, res8);
- break;
-
- case 0x13: /* 13 ADC Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_adc16();
- putreg16 (reg, res16);
- break;
-
- case 0x14: /* 14 ADC regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_adc8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x15: /* 15 ADC eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_adc16();
- putreg16 (regax, res16);
- break;
-
- case 0x16: /* 16 PUSH segregs[regss] */
- push (segregs[regss]);
- break;
-
- case 0x17: /* 17 POP segregs[regss] */
- segregs[regss] = pop();
- break;
-
- case 0x18: /* 18 SBB Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_sbb8();
- writerm8 (rm, res8);
- break;
-
- case 0x19: /* 19 SBB Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_sbb16();
- writerm16 (rm, res16);
- break;
-
- case 0x1A: /* 1A SBB Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_sbb8();
- putreg8 (reg, res8);
- break;
-
- case 0x1B: /* 1B SBB Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_sbb16();
- putreg16 (reg, res16);
- break;
-
- case 0x1C: /* 1C SBB regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_sbb8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x1D: /* 1D SBB eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_sbb16();
- putreg16 (regax, res16);
- break;
-
- case 0x1E: /* 1E PUSH segregs[regds] */
- push (segregs[regds]);
- break;
-
- case 0x1F: /* 1F POP segregs[regds] */
- segregs[regds] = pop();
- break;
-
- case 0x20: /* 20 AND Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_and8();
- writerm8 (rm, res8);
- break;
-
- case 0x21: /* 21 AND Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_and16();
- writerm16 (rm, res16);
- break;
-
- case 0x22: /* 22 AND Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_and8();
- putreg8 (reg, res8);
- break;
-
- case 0x23: /* 23 AND Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_and16();
- putreg16 (reg, res16);
- break;
-
- case 0x24: /* 24 AND regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_and8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x25: /* 25 AND eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_and16();
- putreg16 (regax, res16);
- break;
-
- case 0x27: /* 27 DAA */
- if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) {
- oper1 = regs.byteregs[regal] + 6;
- regs.byteregs[regal] = oper1 & 255;
- if (oper1 & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- af = 1;
- }
- else {
- af = 0;
- }
-
- if ( ( (regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1) ) {
- regs.byteregs[regal] = regs.byteregs[regal] + 0x60;
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- regs.byteregs[regal] = regs.byteregs[regal] & 255;
- flag_szp8 (regs.byteregs[regal]);
- break;
-
- case 0x28: /* 28 SUB Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_sub8();
- writerm8 (rm, res8);
- break;
-
- case 0x29: /* 29 SUB Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_sub16();
- writerm16 (rm, res16);
- break;
-
- case 0x2A: /* 2A SUB Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_sub8();
- putreg8 (reg, res8);
- break;
-
- case 0x2B: /* 2B SUB Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_sub16();
- putreg16 (reg, res16);
- break;
-
- case 0x2C: /* 2C SUB regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_sub8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x2D: /* 2D SUB eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_sub16();
- putreg16 (regax, res16);
- break;
-
- case 0x2F: /* 2F DAS */
- if ( ( (regs.byteregs[regal] & 15) > 9) || (af == 1) ) {
- oper1 = regs.byteregs[regal] - 6;
- regs.byteregs[regal] = oper1 & 255;
- if (oper1 & 0xFF00) {
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- af = 1;
- }
- else {
- af = 0;
- }
-
- if ( ( (regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1) ) {
- regs.byteregs[regal] = regs.byteregs[regal] - 0x60;
- cf = 1;
- }
- else {
- cf = 0;
- }
-
- flag_szp8 (regs.byteregs[regal]);
- break;
-
- case 0x30: /* 30 XOR Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- op_xor8();
- writerm8 (rm, res8);
- break;
-
- case 0x31: /* 31 XOR Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- op_xor16();
- writerm16 (rm, res16);
- break;
-
- case 0x32: /* 32 XOR Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- op_xor8();
- putreg8 (reg, res8);
- break;
-
- case 0x33: /* 33 XOR Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- op_xor16();
- putreg16 (reg, res16);
- break;
-
- case 0x34: /* 34 XOR regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- op_xor8();
- regs.byteregs[regal] = res8;
- break;
-
- case 0x35: /* 35 XOR eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- op_xor16();
- putreg16 (regax, res16);
- break;
-
- case 0x37: /* 37 AAA ASCII */
- if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) {
- regs.byteregs[regal] = regs.byteregs[regal] + 6;
- regs.byteregs[regah] = regs.byteregs[regah] + 1;
- af = 1;
- cf = 1;
- }
- else {
- af = 0;
- cf = 0;
- }
-
- regs.byteregs[regal] = regs.byteregs[regal] & 0xF;
- break;
-
- case 0x38: /* 38 CMP Eb Gb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getreg8 (reg);
- flag_sub8 (oper1b, oper2b);
- break;
-
- case 0x39: /* 39 CMP Ev Gv */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getreg16 (reg);
- flag_sub16 (oper1, oper2);
- break;
-
- case 0x3A: /* 3A CMP Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- flag_sub8 (oper1b, oper2b);
- break;
-
- case 0x3B: /* 3B CMP Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- flag_sub16 (oper1, oper2);
- break;
-
- case 0x3C: /* 3C CMP regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- flag_sub8 (oper1b, oper2b);
- break;
-
- case 0x3D: /* 3D CMP eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- flag_sub16 (oper1, oper2);
- break;
-
- case 0x3F: /* 3F AAS ASCII */
- if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) {
- regs.byteregs[regal] = regs.byteregs[regal] - 6;
- regs.byteregs[regah] = regs.byteregs[regah] - 1;
- af = 1;
- cf = 1;
- }
- else {
- af = 0;
- cf = 0;
- }
-
- regs.byteregs[regal] = regs.byteregs[regal] & 0xF;
- break;
-
- case 0x40: /* 40 INC eAX */
- oldcf = cf;
- oper1 = getreg16 (regax);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regax, res16);
- break;
-
- case 0x41: /* 41 INC eCX */
- oldcf = cf;
- oper1 = getreg16 (regcx);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regcx, res16);
- break;
-
- case 0x42: /* 42 INC eDX */
- oldcf = cf;
- oper1 = getreg16 (regdx);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regdx, res16);
- break;
-
- case 0x43: /* 43 INC eBX */
- oldcf = cf;
- oper1 = getreg16 (regbx);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regbx, res16);
- break;
-
- case 0x44: /* 44 INC eSP */
- oldcf = cf;
- oper1 = getreg16 (regsp);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regsp, res16);
- break;
-
- case 0x45: /* 45 INC eBP */
- oldcf = cf;
- oper1 = getreg16 (regbp);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regbp, res16);
- break;
-
- case 0x46: /* 46 INC eSI */
- oldcf = cf;
- oper1 = getreg16 (regsi);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regsi, res16);
- break;
-
- case 0x47: /* 47 INC eDI */
- oldcf = cf;
- oper1 = getreg16 (regdi);
- oper2 = 1;
- op_add16();
- cf = oldcf;
- putreg16 (regdi, res16);
- break;
-
- case 0x48: /* 48 DEC eAX */
- oldcf = cf;
- oper1 = getreg16 (regax);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regax, res16);
- break;
-
- case 0x49: /* 49 DEC eCX */
- oldcf = cf;
- oper1 = getreg16 (regcx);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regcx, res16);
- break;
-
- case 0x4A: /* 4A DEC eDX */
- oldcf = cf;
- oper1 = getreg16 (regdx);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regdx, res16);
- break;
-
- case 0x4B: /* 4B DEC eBX */
- oldcf = cf;
- oper1 = getreg16 (regbx);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regbx, res16);
- break;
-
- case 0x4C: /* 4C DEC eSP */
- oldcf = cf;
- oper1 = getreg16 (regsp);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regsp, res16);
- break;
-
- case 0x4D: /* 4D DEC eBP */
- oldcf = cf;
- oper1 = getreg16 (regbp);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regbp, res16);
- break;
-
- case 0x4E: /* 4E DEC eSI */
- oldcf = cf;
- oper1 = getreg16 (regsi);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regsi, res16);
- break;
-
- case 0x4F: /* 4F DEC eDI */
- oldcf = cf;
- oper1 = getreg16 (regdi);
- oper2 = 1;
- op_sub16();
- cf = oldcf;
- putreg16 (regdi, res16);
- break;
-
- case 0x50: /* 50 PUSH eAX */
- push (getreg16 (regax) );
- break;
-
- case 0x51: /* 51 PUSH eCX */
- push (getreg16 (regcx) );
- break;
-
- case 0x52: /* 52 PUSH eDX */
- push (getreg16 (regdx) );
- break;
-
- case 0x53: /* 53 PUSH eBX */
- push (getreg16 (regbx) );
- break;
-
- case 0x54: /* 54 PUSH eSP */
- push (getreg16 (regsp) - 2);
- break;
-
- case 0x55: /* 55 PUSH eBP */
- push (getreg16 (regbp) );
- break;
-
- case 0x56: /* 56 PUSH eSI */
- push (getreg16 (regsi) );
- break;
-
- case 0x57: /* 57 PUSH eDI */
- push (getreg16 (regdi) );
- break;
-
- case 0x58: /* 58 POP eAX */
- putreg16 (regax, pop() );
- break;
-
- case 0x59: /* 59 POP eCX */
- putreg16 (regcx, pop() );
- break;
-
- case 0x5A: /* 5A POP eDX */
- putreg16 (regdx, pop() );
- break;
-
- case 0x5B: /* 5B POP eBX */
- putreg16 (regbx, pop() );
- break;
-
- case 0x5C: /* 5C POP eSP */
- putreg16 (regsp, pop() );
- break;
-
- case 0x5D: /* 5D POP eBP */
- putreg16 (regbp, pop() );
- break;
-
- case 0x5E: /* 5E POP eSI */
- putreg16 (regsi, pop() );
- break;
-
- case 0x5F: /* 5F POP eDI */
- putreg16 (regdi, pop() );
- break;
-
- case 0x60: /* 60 PUSHA (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- oldsp = getreg16 (regsp);
- push (getreg16 (regax) );
- push (getreg16 (regcx) );
- push (getreg16 (regdx) );
- push (getreg16 (regbx) );
- push (oldsp);
- push (getreg16 (regbp) );
- push (getreg16 (regsi) );
- push (getreg16 (regdi) );
- break;
-
- case 0x61: /* 61 POPA (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- putreg16 (regdi, pop() );
- putreg16 (regsi, pop() );
- putreg16 (regbp, pop() );
- dummy = pop();
- putreg16 (regbx, pop() );
- putreg16 (regdx, pop() );
- putreg16 (regcx, pop() );
- putreg16 (regax, pop() );
- break;
-
- case 0x62: /* 62 BOUND Gv, Ev (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- modregrm();
- getea (rm);
- if (signext32 (getreg16 (reg) ) < signext32 ( getmem16 (ea >> 4, ea & 15) ) ) {
- intcall86 (5); //bounds check exception
- }
- else {
- ea += 2;
- if (signext32 (getreg16 (reg) ) > signext32 ( getmem16 (ea >> 4, ea & 15) ) ) {
- intcall86(5); //bounds check exception
- }
- }
- break;
-
- case 0x68: /* 68 PUSH Iv (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- push (getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0x69: /* 69 IMUL Gv Ev Iv (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- modregrm();
- temp1 = readrm16 (rm);
- temp2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- if ( (temp1 & 0x8000L) == 0x8000L) {
- temp1 = temp1 | 0xFFFF0000L;
- }
-
- if ( (temp2 & 0x8000L) == 0x8000L) {
- temp2 = temp2 | 0xFFFF0000L;
- }
-
- temp3 = temp1 * temp2;
- putreg16 (reg, temp3 & 0xFFFFL);
- if (temp3 & 0xFFFF0000L) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
- break;
-
- case 0x6A: /* 6A PUSH Ib (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- push (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- break;
-
- case 0x6B: /* 6B IMUL Gv Eb Ib (80186+) */
- if (!x86_cpu_v20)
- goto nov20;
- modregrm();
- temp1 = readrm16 (rm);
- temp2 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if ( (temp1 & 0x8000L) == 0x8000L) {
- temp1 = temp1 | 0xFFFF0000L;
- }
-
- if ( (temp2 & 0x8000L) == 0x8000L) {
- temp2 = temp2 | 0xFFFF0000L;
- }
-
- temp3 = temp1 * temp2;
- putreg16 (reg, temp3 & 0xFFFFL);
- if (temp3 & 0xFFFF0000L) {
- cf = 1;
- of = 1;
- }
- else {
- cf = 0;
- of = 0;
- }
- break;
-
- case 0x6C: /* 6E INSB */
- if (!x86_cpu_v20)
- goto nov20;
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem8 (useseg, getreg16 (regsi) , portin (regs.wordregs[regdx]) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 1);
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 1);
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0x6D: /* 6F INSW */
- if (!x86_cpu_v20)
- goto nov20;
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem16 (useseg, getreg16 (regsi) , portin16 (regs.wordregs[regdx]) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 2);
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 2);
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0x6E: /* 6E OUTSB */
- if (!x86_cpu_v20)
- goto nov20;
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- portout (regs.wordregs[regdx], getmem8 (useseg, getreg16 (regsi) ) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 1);
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 1);
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0x6F: /* 6F OUTSW */
- if (!x86_cpu_v20)
- goto nov20;
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- portout16 (regs.wordregs[regdx], getmem16 (useseg, getreg16 (regsi) ) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 2);
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 2);
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0x70: /* 70 JO Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (of) {
- ip = ip + temp16;
- }
- break;
-
- case 0x71: /* 71 JNO Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!of) {
- ip = ip + temp16;
- }
- break;
-
- case 0x72: /* 72 JB Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (cf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x73: /* 73 JNB Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!cf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x74: /* 74 JZ Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x75: /* 75 JNZ Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x76: /* 76 JBE Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (cf || zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x77: /* 77 JA Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!cf && !zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x78: /* 78 JS Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (sf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x79: /* 79 JNS Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!sf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7A: /* 7A JPE Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (pf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7B: /* 7B JPO Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!pf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7C: /* 7C JL Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (sf != of) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7D: /* 7D JGE Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (sf == of) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7E: /* 7E JLE Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if ( (sf != of) || zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0x7F: /* 7F JG Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (!zf && (sf == of) ) {
- ip = ip + temp16;
- }
- break;
-
- case 0x80:
- case 0x82: /* 80/82 GRP1 Eb Ib */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- switch (reg) {
- case 0:
- op_add8();
- break;
- case 1:
- op_or8();
- break;
- case 2:
- op_adc8();
- break;
- case 3:
- op_sbb8();
- break;
- case 4:
- op_and8();
- break;
- case 5:
- op_sub8();
- break;
- case 6:
- op_xor8();
- break;
- case 7:
- flag_sub8 (oper1b, oper2b);
- break;
- default:
- break; /* to avoid compiler warnings */
- }
-
- if (reg < 7) {
- writerm8 (rm, res8);
- }
- break;
-
- case 0x81: /* 81 GRP1 Ev Iv */
- case 0x83: /* 83 GRP1 Ev Ib */
- modregrm();
- oper1 = readrm16 (rm);
- if (opcode == 0x81) {
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- }
- else {
- oper2 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- }
-
- switch (reg) {
- case 0:
- op_add16();
- break;
- case 1:
- op_or16();
- break;
- case 2:
- op_adc16();
- break;
- case 3:
- op_sbb16();
- break;
- case 4:
- op_and16();
- break;
- case 5:
- op_sub16();
- break;
- case 6:
- op_xor16();
- break;
- case 7:
- flag_sub16 (oper1, oper2);
- break;
- default:
- break; /* to avoid compiler warnings */
- }
-
- if (reg < 7) {
- writerm16 (rm, res16);
- }
- break;
-
- case 0x84: /* 84 TEST Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- oper2b = readrm8 (rm);
- flag_log8 (oper1b & oper2b);
- break;
-
- case 0x85: /* 85 TEST Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- oper2 = readrm16 (rm);
- flag_log16 (oper1 & oper2);
- break;
-
- case 0x86: /* 86 XCHG Gb Eb */
- modregrm();
- oper1b = getreg8 (reg);
- putreg8 (reg, readrm8 (rm) );
- writerm8 (rm, oper1b);
- break;
-
- case 0x87: /* 87 XCHG Gv Ev */
- modregrm();
- oper1 = getreg16 (reg);
- putreg16 (reg, readrm16 (rm) );
- writerm16 (rm, oper1);
- break;
-
- case 0x88: /* 88 MOV Eb Gb */
- modregrm();
- writerm8 (rm, getreg8 (reg) );
- break;
-
- case 0x89: /* 89 MOV Ev Gv */
- modregrm();
- writerm16 (rm, getreg16 (reg) );
- break;
-
- case 0x8A: /* 8A MOV Gb Eb */
- modregrm();
- putreg8 (reg, readrm8 (rm) );
- break;
-
- case 0x8B: /* 8B MOV Gv Ev */
- modregrm();
- putreg16 (reg, readrm16 (rm) );
- break;
-
- case 0x8C: /* 8C MOV Ew Sw */
- modregrm();
- writerm16 (rm, getsegreg (reg) );
- break;
-
- case 0x8D: /* 8D LEA Gv M */
- modregrm();
- getea (rm);
- putreg16 (reg, ea - segbase (useseg) );
- break;
-
- case 0x8E: /* 8E MOV Sw Ew */
- modregrm();
- putsegreg (reg, readrm16 (rm) );
- break;
-
- case 0x8F: /* 8F POP Ev */
- modregrm();
- writerm16 (rm, pop() );
- break;
-
- case 0x90: /* 90 NOP */
- break;
-
- case 0x91: /* 91 XCHG eCX eAX */
- oper1 = getreg16 (regcx);
- putreg16 (regcx, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x92: /* 92 XCHG eDX eAX */
- oper1 = getreg16 (regdx);
- putreg16 (regdx, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x93: /* 93 XCHG eBX eAX */
- oper1 = getreg16 (regbx);
- putreg16 (regbx, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x94: /* 94 XCHG eSP eAX */
- oper1 = getreg16 (regsp);
- putreg16 (regsp, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x95: /* 95 XCHG eBP eAX */
- oper1 = getreg16 (regbp);
- putreg16 (regbp, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x96: /* 96 XCHG eSI eAX */
- oper1 = getreg16 (regsi);
- putreg16 (regsi, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x97: /* 97 XCHG eDI eAX */
- oper1 = getreg16 (regdi);
- putreg16 (regdi, getreg16 (regax) );
- putreg16 (regax, oper1);
- break;
-
- case 0x98: /* 98 CBW */
- if ( (regs.byteregs[regal] & 0x80) == 0x80) {
- regs.byteregs[regah] = 0xFF;
- }
- else {
- regs.byteregs[regah] = 0;
- }
- break;
-
- case 0x99: /* 99 CWD */
- if ( (regs.byteregs[regah] & 0x80) == 0x80) {
- putreg16 (regdx, 0xFFFF);
- }
- else {
- putreg16 (regdx, 0);
- }
- break;
-
- case 0x9A: /* 9A CALL Ap */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- push (segregs[regcs]);
- push (ip);
- ip = oper1;
- segregs[regcs] = oper2;
- break;
-
- case 0x9B: /* 9B WAIT */
- break;
-
- case 0x9C: /* 9C PUSHF */
- push (makeflagsword() | 0xF800);
- break;
-
- case 0x9D: /* 9D POPF */
- temp16 = pop();
- decodeflagsword (temp16);
- break;
-
- case 0x9E: /* 9E SAHF */
- decodeflagsword ( (makeflagsword() & 0xFF00) | regs.byteregs[regah]);
- break;
-
- case 0x9F: /* 9F LAHF */
- regs.byteregs[regah] = makeflagsword() & 0xFF;
- break;
-
- case 0xA0: /* A0 MOV regs.byteregs[regal] Ob */
- regs.byteregs[regal] = getmem8 (useseg, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xA1: /* A1 MOV eAX Ov */
- oper1 = getmem16 (useseg, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- putreg16 (regax, oper1);
- break;
-
- case 0xA2: /* A2 MOV Ob regs.byteregs[regal] */
- putmem8 (useseg, getmem16 (segregs[regcs], ip), regs.byteregs[regal]);
- StepIP (2);
- break;
-
- case 0xA3: /* A3 MOV Ov eAX */
- putmem16 (useseg, getmem16 (segregs[regcs], ip), getreg16 (regax) );
- StepIP (2);
- break;
-
- case 0xA4: /* A4 MOVSB */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem8 (segregs[reges], getreg16 (regdi), getmem8 (useseg, getreg16 (regsi) ) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 1);
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 1);
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xA5: /* A5 MOVSW */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem16 (segregs[reges], getreg16 (regdi), getmem16 (useseg, getreg16 (regsi) ) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 2);
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 2);
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xA6: /* A6 CMPSB */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- oper1b = getmem8 (useseg, getreg16 (regsi) );
- oper2b = getmem8 (segregs[reges], getreg16 (regdi) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 1);
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 1);
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- flag_sub8 (oper1b, oper2b);
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- if ( (reptype == 1) && !zf) {
- break;
- }
- else if ( (reptype == 2) && (zf == 1) ) {
- break;
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xA7: /* A7 CMPSW */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- oper1 = getmem16 (useseg, getreg16 (regsi) );
- oper2 = getmem16 (segregs[reges], getreg16 (regdi) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 2);
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 2);
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- flag_sub16 (oper1, oper2);
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- if ( (reptype == 1) && !zf) {
- break;
- }
-
- if ( (reptype == 2) && (zf == 1) ) {
- break;
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xA8: /* A8 TEST regs.byteregs[regal] Ib */
- oper1b = regs.byteregs[regal];
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- flag_log8 (oper1b & oper2b);
- break;
-
- case 0xA9: /* A9 TEST eAX Iv */
- oper1 = getreg16 (regax);
- oper2 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- flag_log16 (oper1 & oper2);
- break;
-
- case 0xAA: /* AA STOSB */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem8 (segregs[reges], getreg16 (regdi), regs.byteregs[regal]);
- if (df) {
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xAB: /* AB STOSW */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- putmem16 (segregs[reges], getreg16 (regdi), getreg16 (regax) );
- if (df) {
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xAC: /* AC LODSB */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- regs.byteregs[regal] = getmem8 (useseg, getreg16 (regsi) );
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 1);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xAD: /* AD LODSW */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- oper1 = getmem16 (useseg, getreg16 (regsi) );
- putreg16 (regax, oper1);
- if (df) {
- putreg16 (regsi, getreg16 (regsi) - 2);
- }
- else {
- putreg16 (regsi, getreg16 (regsi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xAE: /* AE SCASB */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- oper1b = getmem8 (segregs[reges], getreg16 (regdi) );
- oper2b = regs.byteregs[regal];
- flag_sub8 (oper1b, oper2b);
- if (df) {
- putreg16 (regdi, getreg16 (regdi) - 1);
- }
- else {
- putreg16 (regdi, getreg16 (regdi) + 1);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- if ( (reptype == 1) && !zf) {
- break;
- }
- else if ( (reptype == 2) && (zf == 1) ) {
- break;
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xAF: /* AF SCASW */
- if (reptype && (getreg16 (regcx) == 0) ) {
- break;
- }
-
- oper1 = getmem16 (segregs[reges], getreg16 (regdi) );
- oper2 = getreg16 (regax);
- flag_sub16 (oper1, oper2);
- if (df) {
- putreg16 (regdi, getreg16 (regdi) - 2);
- }
- else {
- putreg16 (regdi, getreg16 (regdi) + 2);
- }
-
- if (reptype) {
- putreg16 (regcx, getreg16 (regcx) - 1);
- }
-
- if ( (reptype == 1) && !zf) {
- break;
- }
- else if ( (reptype == 2) & (zf == 1) ) {
- break;
- }
-
- totalexec++;
- loopcount++;
- if (!reptype) {
- break;
- }
-
- ip = firstip;
- break;
-
- case 0xB0: /* B0 MOV regs.byteregs[regal] Ib */
- regs.byteregs[regal] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB1: /* B1 MOV regs.byteregs[regcl] Ib */
- regs.byteregs[regcl] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB2: /* B2 MOV regs.byteregs[regdl] Ib */
- regs.byteregs[regdl] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB3: /* B3 MOV regs.byteregs[regbl] Ib */
- regs.byteregs[regbl] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB4: /* B4 MOV regs.byteregs[regah] Ib */
- regs.byteregs[regah] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB5: /* B5 MOV regs.byteregs[regch] Ib */
- regs.byteregs[regch] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB6: /* B6 MOV regs.byteregs[regdh] Ib */
- regs.byteregs[regdh] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB7: /* B7 MOV regs.byteregs[regbh] Ib */
- regs.byteregs[regbh] = getmem8 (segregs[regcs], ip);
- StepIP (1);
- break;
-
- case 0xB8: /* B8 MOV eAX Iv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- putreg16 (regax, oper1);
- break;
-
- case 0xB9: /* B9 MOV eCX Iv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- putreg16 (regcx, oper1);
- break;
-
- case 0xBA: /* BA MOV eDX Iv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- putreg16 (regdx, oper1);
- break;
-
- case 0xBB: /* BB MOV eBX Iv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- putreg16 (regbx, oper1);
- break;
-
- case 0xBC: /* BC MOV eSP Iv */
- putreg16 (regsp, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xBD: /* BD MOV eBP Iv */
- putreg16 (regbp, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xBE: /* BE MOV eSI Iv */
- putreg16 (regsi, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xBF: /* BF MOV eDI Iv */
- putreg16 (regdi, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xC0: /* C0 GRP2 byte imm8 (80186+) */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- writerm8 (rm, op_grp2_8 (oper2b) );
- break;
-
- case 0xC1: /* C1 GRP2 word imm8 (80186+) */
- modregrm();
- oper1 = readrm16 (rm);
- oper2 = getmem8 (segregs[regcs], ip);
- StepIP (1);
- writerm16 (rm, op_grp2_16 ( (uint8_t) oper2) );
- break;
-
- case 0xC2: /* C2 RET Iw */
- oper1 = getmem16 (segregs[regcs], ip);
- ip = pop();
- putreg16 (regsp, getreg16 (regsp) + oper1);
- break;
-
- case 0xC3: /* C3 RET */
- ip = pop();
- break;
-
- case 0xC4: /* C4 LES Gv Mp */
- modregrm();
- getea (rm);
- putreg16 (reg, read86 (ea) + read86 (ea + 1) * 256);
- segregs[reges] = read86 (ea + 2) + read86 (ea + 3) * 256;
- break;
-
- case 0xC5: /* C5 LDS Gv Mp */
- modregrm();
- getea (rm);
- putreg16 (reg, read86 (ea) + read86 (ea + 1) * 256);
- segregs[regds] = read86 (ea + 2) + read86 (ea + 3) * 256;
- break;
-
- case 0xC6: /* C6 MOV Eb Ib */
- modregrm();
- writerm8 (rm, getmem8 (segregs[regcs], ip) );
- StepIP (1);
- break;
-
- case 0xC7: /* C7 MOV Ev Iv */
- modregrm();
- writerm16 (rm, getmem16 (segregs[regcs], ip) );
- StepIP (2);
- break;
-
- case 0xC8: /* C8 ENTER (80186+) */
- stacksize = getmem16 (segregs[regcs], ip);
- StepIP (2);
- nestlev = getmem8 (segregs[regcs], ip);
- StepIP (1);
- push (getreg16 (regbp) );
- frametemp = getreg16 (regsp);
- if (nestlev) {
- for (temp16 = 1; temp16 < nestlev; temp16++) {
- putreg16 (regbp, getreg16 (regbp) - 2);
- push (getreg16 (regbp) );
- }
-
- push (getreg16 (regsp) );
- }
-
- putreg16 (regbp, frametemp);
- putreg16 (regsp, getreg16 (regbp) - stacksize);
-
- break;
-
- case 0xC9: /* C9 LEAVE (80186+) */
- putreg16 (regsp, getreg16 (regbp) );
- putreg16 (regbp, pop() );
-
- break;
-
- case 0xCA: /* CA RETF Iw */
- oper1 = getmem16 (segregs[regcs], ip);
- ip = pop();
- segregs[regcs] = pop();
- putreg16 (regsp, getreg16 (regsp) + oper1);
- break;
-
- case 0xCB: /* CB RETF */
- ip = pop();;
- segregs[regcs] = pop();
- break;
-
- case 0xCC: /* CC INT 3 */
- intcall86 (3);
- break;
-
- case 0xCD: /* CD INT Ib */
- oper1b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- intcall86 (oper1b);
- break;
-
- case 0xCE: /* CE INTO */
- if (of) {
- intcall86 (4);
- }
- break;
-
- case 0xCF: /* CF IRET */
- ip = pop();
- segregs[regcs] = pop();
- decodeflagsword (pop() );
-
- /*
- * if (net.enabled) net.canrecv = 1;
- */
- break;
-
- case 0xD0: /* D0 GRP2 Eb 1 */
- modregrm();
- oper1b = readrm8 (rm);
- writerm8 (rm, op_grp2_8 (1) );
- break;
-
- case 0xD1: /* D1 GRP2 Ev 1 */
- modregrm();
- oper1 = readrm16 (rm);
- writerm16 (rm, op_grp2_16 (1) );
- break;
-
- case 0xD2: /* D2 GRP2 Eb regs.byteregs[regcl] */
- modregrm();
- oper1b = readrm8 (rm);
- writerm8 (rm, op_grp2_8 (regs.byteregs[regcl]) );
- break;
-
- case 0xD3: /* D3 GRP2 Ev regs.byteregs[regcl] */
- modregrm();
- oper1 = readrm16 (rm);
- writerm16 (rm, op_grp2_16 (regs.byteregs[regcl]) );
- break;
-
- case 0xD4: /* D4 AAM I0 */
- oper1 = getmem8 (segregs[regcs], ip);
- StepIP (1);
- if (!oper1) {
- intcall86 (0);
- break;
- } /* division by zero */
-
- regs.byteregs[regah] = (regs.byteregs[regal] / oper1) & 255;
- regs.byteregs[regal] = (regs.byteregs[regal] % oper1) & 255;
- flag_szp16 (getreg16 (regax) );
- break;
-
- case 0xD5: /* D5 AAD I0 */
- oper1 = getmem8 (segregs[regcs], ip);
- StepIP (1);
- regs.byteregs[regal] = (regs.byteregs[regah] * oper1 + regs.byteregs[regal]) & 255;
- regs.byteregs[regah] = 0;
- flag_szp16 (regs.byteregs[regah] * oper1 + regs.byteregs[regal]);
- sf = 0;
- break;
-
- case 0xD6: /* D6 XLAT on V20/V30, SALC on 8086/8088 */
-
- if (x86_cpu_v20)
- regs.byteregs[regal] = read86(useseg * 16 + (regs.wordregs[regbx]) + regs.byteregs[regal]);
- else
- regs.byteregs[regal] = cf ? 0xFF : 0x00;
- break;
-
- case 0xD7: /* D7 XLAT */
- regs.byteregs[regal] = read86(useseg * 16 + (regs.wordregs[regbx]) + regs.byteregs[regal]);
- break;
-
- case 0xD8:
- case 0xD9:
- case 0xDA:
- case 0xDB:
- case 0xDC:
- case 0xDE:
- case 0xDD:
- case 0xDF: /* escape to x87 FPU (unsupported) */
- modregrm();
- break;
-
- case 0xE0: /* E0 LOOPNZ Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- putreg16 (regcx, getreg16 (regcx) - 1);
- if ( (getreg16 (regcx) ) && !zf) {
- ip = ip + temp16;
- }
- break;
-
- case 0xE1: /* E1 LOOPZ Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- putreg16 (regcx, (getreg16 (regcx) ) - 1);
- if ( (getreg16 (regcx) ) && (zf == 1) ) {
- ip = ip + temp16;
- }
- break;
-
- case 0xE2: /* E2 LOOP Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- putreg16 (regcx, (getreg16 (regcx) ) - 1);
- if (getreg16 (regcx) ) {
- ip = ip + temp16;
- }
- break;
-
- case 0xE3: /* E3 JCXZ Jb */
- temp16 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- if (! (getreg16 (regcx) ) ) {
- ip = ip + temp16;
- }
- break;
-
- case 0xE4: /* E4 IN regs.byteregs[regal] Ib */
- oper1b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- regs.byteregs[regal] = (uint8_t) portin (oper1b);
- break;
-
- case 0xE5: /* E5 IN eAX Ib */
- oper1b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- putreg16 (regax, portin16 (oper1b) );
- break;
-
- case 0xE6: /* E6 OUT Ib regs.byteregs[regal] */
- oper1b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- portout (oper1b, regs.byteregs[regal]);
- break;
-
- case 0xE7: /* E7 OUT Ib eAX */
- oper1b = getmem8 (segregs[regcs], ip);
- StepIP (1);
- portout16 (oper1b, (getreg16 (regax) ) );
- break;
-
- case 0xE8: /* E8 CALL Jv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- push (ip);
- ip = ip + oper1;
- break;
-
- case 0xE9: /* E9 JMP Jv */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- ip = ip + oper1;
- break;
-
- case 0xEA: /* EA JMP Ap */
- oper1 = getmem16 (segregs[regcs], ip);
- StepIP (2);
- oper2 = getmem16 (segregs[regcs], ip);
- ip = oper1;
- segregs[regcs] = oper2;
- break;
-
- case 0xEB: /* EB JMP Jb */
- oper1 = signext (getmem8 (segregs[regcs], ip) );
- StepIP (1);
- ip = ip + oper1;
- break;
-
- case 0xEC: /* EC IN regs.byteregs[regal] regdx */
- oper1 = (getreg16 (regdx) );
- regs.byteregs[regal] = (uint8_t) portin (oper1);
- break;
-
- case 0xED: /* ED IN eAX regdx */
- oper1 = (getreg16 (regdx) );
- putreg16 (regax, portin16 (oper1) );
- break;
-
- case 0xEE: /* EE OUT regdx regs.byteregs[regal] */
- oper1 = (getreg16 (regdx) );
- portout (oper1, regs.byteregs[regal]);
- break;
-
- case 0xEF: /* EF OUT regdx eAX */
- oper1 = (getreg16 (regdx) );
- portout16 (oper1, (getreg16 (regax) ) );
- break;
-
- case 0xF0: /* F0 LOCK */
- break;
-
- case 0xF4: /* F4 HLT */
- ip--;
- break;
-
- case 0xF5: /* F5 CMC */
- if (!cf) {
- cf = 1;
- }
- else {
- cf = 0;
- }
- break;
-
- case 0xF6: /* F6 GRP3a Eb */
- modregrm();
- oper1b = readrm8 (rm);
- op_grp3_8();
- if ( (reg > 1) && (reg < 4) ) {
- writerm8 (rm, res8);
- }
- break;
-
- case 0xF7: /* F7 GRP3b Ev */
- modregrm();
- oper1 = readrm16 (rm);
- op_grp3_16();
- if ( (reg > 1) && (reg < 4) ) {
- writerm16 (rm, res16);
- }
- break;
-
- case 0xF8: /* F8 CLC */
- cf = 0;
- break;
-
- case 0xF9: /* F9 STC */
- cf = 1;
- break;
-
- case 0xFA: /* FA CLI */
- ifl = 0;
- break;
-
- case 0xFB: /* FB STI */
- ifl = 1;
- break;
-
- case 0xFC: /* FC CLD */
- df = 0;
- break;
-
- case 0xFD: /* FD STD */
- df = 1;
- break;
-
- case 0xFE: /* FE GRP4 Eb */
- modregrm();
- oper1b = readrm8 (rm);
- oper2b = 1;
- if (!reg) {
- tempcf = cf;
- res8 = oper1b + oper2b;
- flag_add8 (oper1b, oper2b);
- cf = tempcf;
- writerm8 (rm, res8);
- }
- else {
- tempcf = cf;
- res8 = oper1b - oper2b;
- flag_sub8 (oper1b, oper2b);
- cf = tempcf;
- writerm8 (rm, res8);
- }
- break;
-
- case 0xFF: /* FF GRP5 Ev */
- modregrm();
- oper1 = readrm16 (rm);
- op_grp5();
- break;
-
- default:
-nov20:
- if (x86_cpu_v20)
- intcall86 (6); /* trip invalid opcode exception (this occurs on the 80186+, 8086/8088 CPUs treat them as NOPs. */
- /* technically they aren't exactly like NOPs in most cases, but for our pursoses, that's accurate enough. */
-
- if (verbose) {
- write_log ("Illegal opcode: %02X @ %04X:%04X\n", opcode, savecs, saveip);
- }
- break;
- }
-
- if (!running) {
- return;
- }
- }
-}
-