1
0
Fork 0

New core_normal based on old core_16 for handling real and protected mode code.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1199
This commit is contained in:
Sjoerd van der Berg 2003-08-22 20:13:48 +00:00
parent c71f9c3d1f
commit e18440ce32
12 changed files with 3726 additions and 15 deletions

View file

@ -1,6 +1,6 @@
SUBDIRS = core_16 core_full
SUBDIRS = core_16 core_full core_normal
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp core_full.cpp instructions.h \
paging.cpp lazyflags.h
paging.cpp lazyflags.h core_normal.cpp

221
src/cpu/core_normal.cpp Normal file
View file

@ -0,0 +1,221 @@
/*
* Copyright (C) 2002-2003 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 Library 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 "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
#define SegBase(c) SegPhys(c)
#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
#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
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_SEG 0x1
#define PREFIX_ADDR 0x2
#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR)
#define PREFIX_REP 0x4
#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG)
#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR)
#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP)
#define DO_PREFIX_SEG(_SEG) \
core.prefixes|=PREFIX_SEG; \
core.seg_prefix_base=SegBase(_SEG); \
goto restart_prefix;
#define DO_PREFIX_ADDR() \
core.prefixes^=PREFIX_ADDR; \
goto restart_prefix;
#define DO_PREFIX_REP(_ZERO) \
core.prefixes|=PREFIX_REP; \
core.rep_zero=_ZERO; \
goto restart_prefix;
typedef PhysPt (*GetEATable[256])(void);
static struct {
Bitu opcode_index;
Bitu prefixes;
Bitu index_default;
Bitu prefix_default;
PhysPt op_start;
PhysPt ip_lookup;
PhysPt seg_prefix_base;
bool rep_zero;
GetEATable * ea_table;
} core;
#include "instructions.h"
#include "core_normal/support.h"
#include "core_normal/string.h"
static GetEATable * EAPrefixTable[8] = {
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
};
#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)
#define EALookupTable (*(core.ea_table))
static Bits CPU_Core_Normal_Decode_Trap(void);
static Bits CPU_Core_Normal_Decode(void) {
decode_start:
LOADIP;
flags.type=t_UNKNOWN;
while (CPU_Cycles>0) {
core.op_start=core.ip_lookup;
core.opcode_index=core.index_default;
core.prefixes=core.prefix_default;
#if C_DEBUG
cycle_count++;
#if C_HEAVY_DEBUG
SAVEIP;
if (DEBUG_HeavyIsBreakpoint()) {
LEAVECORE;
return debugCallback;
};
#endif
#endif
CPU_Cycles--;
restart_prefix:
core.ea_table=EAPrefixTable[core.prefixes];
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:
ADDIPFAST(-1);
LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb());
}
}
decode_end:
LEAVECORE;
return CBRET_NONE;
}
static Bits CPU_Core_Normal_Decode_Trap(void) {
Bits oldCycles = CPU_Cycles;
CPU_Cycles = 1;
Bits ret=CPU_Core_Normal_Decode();
Interrupt(1);
CPU_Cycles = oldCycles-1;
cpudecoder = &CPU_Core_Normal_Decode;
return ret;
}
void CPU_Core_Normal_Start(bool big) {
if (GETFLAG(TF)) cpudecoder=CPU_Core_Normal_Decode_Trap;
else cpudecoder=CPU_Core_Normal_Decode;
if (big) {
core.index_default=0x200;
core.prefix_default=PREFIX_ADDR;
} else {
core.index_default=0;
core.prefix_default=0;
}
}

View file

@ -0,0 +1,3 @@
noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \
prefix_66_0f.h string.h

View file

@ -0,0 +1,143 @@
/*
* Copyright (C) 2002 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 Library 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); \
} \
}

View file

@ -0,0 +1,449 @@
/*
* Copyright (C) 2002 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 Library 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 */
{
GetRM;Bitu which=(rm>>3)&7;
switch (which) {
case 0x00: /* SLDT */
case 0x01: /* STR */
{
Bitu saveval;
if (!which) CPU_SLDT(saveval);
else CPU_STR(saveval);
if (rm >= 0xc0) {GetEArw;*earw=saveval;}
else {GetEAa;SaveMw(eaa,saveval);}
}
break;
case 0x02:case 0x03:case 0x04:case 0x05:
{
FillFlags();
Bitu loadval;
if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
else {GetEAa;loadval=LoadMw(eaa);}
break;
switch (which) {
case 0x02:CPU_LLDT(loadval);break;
case 0x03:CPU_LTR(loadval);break;
case 0x04:CPU_VERR(loadval);break;
case 0x05:CPU_VERW(loadval);break;
}
}
default:
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
}
}
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,base;
switch (which) {
case 0x00: /* SGDT */
CPU_SGDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
break;
case 0x01: /* SIDT */
CPU_SIDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
break;
case 0x02: /* LGDT */
CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF);
break;
case 0x03: /* LIDT */
CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF);
break;
case 0x04: /* SMSW */
CPU_SMSW(limit);
SaveMw(eaa,limit);
break;
case 0x06: /* LMSW */
limit=LoadMw(eaa);
if (!CPU_LMSW(limit)) goto decode_end;
break;
}
} else {
GetEArw;Bitu limit;
switch (which) {
case 0x04: /* SMSW */
CPU_SMSW(limit);
*earw=limit;
break;
case 0x06: /* LMSW */
if (!CPU_LMSW(*earw)) goto decode_end;
break;
default:
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
break;
}
}
}
break;
CASE_0F_W(0x02) /* LAR Gw,Ew */
{
FillFlags();
GetRMrw;Bitu ar;
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 */
{
FillFlags();
GetRMrw;Bitu limit;
if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit);
} else {
GetEAa;CPU_LSL(LoadMw(eaa),limit);
}
*rmrw=(Bit16u)limit;
}
break;
CASE_0F_B(0x20) /* MOV Rd.CRx */
{
GetRM;
Bitu which=(rm >> 3) & 7;
if (rm >= 0xc0 ) {
GetEArd;
*eard=CPU_GET_CRX(which);
} else {
GetEAa;
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%d with non-register",which);
}
}
break;
CASE_0F_B(0x22) /* MOV CRx,Rd */
{
GetRM;
Bitu which=(rm >> 3) & 7;
if (rm >= 0xc0 ) {
GetEArd;
if (!CPU_SET_CRX(which,*eard)) goto decode_end;
} else {
GetEAa;
LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which);
}
}
break;
CASE_0F_B(0x23) /* MOV DRx,Rd */
{
GetRM;
Bitu which=(rm >> 3) & 7;
if (rm >= 0xc0 ) {
GetEArd;
} else {
GetEAa;
LOG(LOG_CPU,LOG_ERROR)("MOV DR%,XXX with non-register",which);
}
}
break;
CASE_0F_W(0x80) /* JO */
JumpSIw(get_OF());break;
CASE_0F_W(0x81) /* JNO */
JumpSIw(!get_OF());break;
CASE_0F_W(0x82) /* JB */
JumpSIw(get_CF());break;
CASE_0F_W(0x83) /* JNB */
JumpSIw(!get_CF());break;
CASE_0F_W(0x84) /* JZ */
JumpSIw(get_ZF());break;
CASE_0F_W(0x85) /* JNZ */
JumpSIw(!get_ZF());break;
CASE_0F_W(0x86) /* JBE */
JumpSIw(get_CF() || get_ZF());break;
CASE_0F_W(0x87) /* JNBE */
JumpSIw(!get_CF() && !get_ZF());break;
CASE_0F_W(0x88) /* JS */
JumpSIw(get_SF());break;
CASE_0F_W(0x89) /* JNS */
JumpSIw(!get_SF());break;
CASE_0F_W(0x8a) /* JP */
JumpSIw(get_PF());break;
CASE_0F_W(0x8b) /* JNP */
JumpSIw(!get_PF());break;
CASE_0F_W(0x8c) /* JL */
JumpSIw(get_SF() != get_OF());break;
CASE_0F_W(0x8d) /* JNL */
JumpSIw(get_SF() == get_OF());break;
CASE_0F_W(0x8e) /* JLE */
JumpSIw(get_ZF() || (get_SF() != get_OF()));break;
CASE_0F_W(0x8f) /* JNLE */
JumpSIw((get_SF() == get_OF()) && !get_ZF());break;
CASE_0F_B(0x90) /* SETO */
SETcc(get_OF());break;
CASE_0F_B(0x91) /* SETNO */
SETcc(!get_OF());break;
CASE_0F_B(0x92) /* SETB */
SETcc(get_CF());break;
CASE_0F_B(0x93) /* SETNB */
SETcc(!get_CF());break;
CASE_0F_B(0x94) /* SETZ */
SETcc(get_ZF());break;
CASE_0F_B(0x95) /* SETNZ */
SETcc(!get_ZF()); break;
CASE_0F_B(0x96) /* SETBE */
SETcc(get_CF() || get_ZF());break;
CASE_0F_B(0x97) /* SETNBE */
SETcc(!get_CF() && !get_ZF());break;
CASE_0F_B(0x98) /* SETS */
SETcc(get_SF());break;
CASE_0F_B(0x99) /* SETNS */
SETcc(!get_SF());break;
CASE_0F_B(0x9a) /* SETP */
SETcc(get_PF());break;
CASE_0F_B(0x9b) /* SETNP */
SETcc(!get_PF());break;
CASE_0F_B(0x9c) /* SETL */
SETcc(get_SF() != get_OF());break;
CASE_0F_B(0x9d) /* SETNL */
SETcc(get_SF() == get_OF());break;
CASE_0F_B(0x9e) /* SETLE */
SETcc(get_ZF() || (get_SF() != get_OF()));break;
CASE_0F_B(0x9f) /* SETNLE */
SETcc((get_SF() == get_OF()) && !get_ZF());break;
CASE_0F_W(0xa0) /* PUSH FS */
Push_16(SegValue(fs));break;
CASE_0F_W(0xa1) /* POP FS */
CPU_SetSegGeneral(fs,Pop_16());break;
CASE_0F_B(0xa2) /* CPUID */
CPU_CPUID();break;
CASE_0F_W(0xa3) /* BT Ew,Gw */
{
GetRMrw;
Bit16u mask=1 << (*rmrw & 15);
if (rm >= 0xc0 ) {
GetEArw;
SETFLAGBIT(CF,(*earw & mask));
} else {
GetEAa;Bit16u old=LoadMw(eaa);
SETFLAGBIT(CF,(old & mask));
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
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 */
CPU_SetSegGeneral(gs,Pop_16());break;
CASE_0F_W(0xab) /* BTS Ew,Gw */
{
GetRMrw;
Bit16u mask=1 << (*rmrw & 15);
if (rm >= 0xc0 ) {
GetEArw;
SETFLAGBIT(CF,(*earw & mask));
*earw|=mask;
} else {
GetEAa;Bit16u old=LoadMw(eaa);
SETFLAGBIT(CF,(old & mask));
SaveMw(eaa,old | mask);
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
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_W(0xb2) /* LSS Ew */
{
GetRMrw;GetEAa;
*rmrw=LoadMw(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+2));
break;
}
CASE_0F_W(0xb3) /* BTR Ew,Gw */
{
GetRMrw;
Bit16u mask=1 << (*rmrw & 15);
if (rm >= 0xc0 ) {
GetEArw;
SETFLAGBIT(CF,(*earw & mask));
*earw&= ~mask;
} else {
GetEAa;Bit16u old=LoadMw(eaa);
SETFLAGBIT(CF,(old & mask));
SaveMw(eaa,old & ~mask);
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
break;
}
CASE_0F_W(0xb4) /* LFS Ew */
{
GetRMrw;GetEAa;
*rmrw=LoadMw(eaa);CPU_SetSegGeneral(fs,LoadMw(eaa+2));
break;
}
CASE_0F_W(0xb5) /* LGS Ew */
{
GetRMrw;GetEAa;
*rmrw=LoadMw(eaa);CPU_SetSegGeneral(gs,LoadMw(eaa+2));
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 */
{
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);
}
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
break;
}
CASE_0F_W(0xbb) /* BTC Ew,Gw */
{
GetRMrw;
Bit16u mask=1 << (*rmrw & 15);
if (rm >= 0xc0 ) {
GetEArw;
SETFLAGBIT(CF,(*earw & mask));
*earw^=mask;
} else {
GetEAa;Bit16u old=LoadMw(eaa);
SETFLAGBIT(CF,(old & mask));
SaveMw(eaa,old ^ mask);
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
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;
}
flags.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;
}
flags.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(0xc8) /* BSWAP EAX */
BSWAP(reg_eax);break;
CASE_0F_B(0xc9) /* BSWAP ECX */
BSWAP(reg_ecx);break;
CASE_0F_B(0xca) /* BSWAP EDX */
BSWAP(reg_edx);break;
CASE_0F_B(0xcb) /* BSWAP EBX */
BSWAP(reg_ebx);break;
CASE_0F_B(0xcc) /* BSWAP ESP */
BSWAP(reg_esp);break;
CASE_0F_B(0xcd) /* BSWAP EBP */
BSWAP(reg_ebp);break;
CASE_0F_B(0xce) /* BSWAP ESI */
BSWAP(reg_esi);break;
CASE_0F_B(0xcf) /* BSWAP EDI */
BSWAP(reg_edi);break;

View file

@ -0,0 +1,611 @@
/*
* Copyright (C) 2002 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 Library 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 */
CPU_SetSegGeneral(es,(Bit16u)Pop_32());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 */
CPU_SetSegGeneral(ss,(Bit16u)Pop_32());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 */
CPU_SetSegGeneral(ds,(Bit16u)Pop_32());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 */
Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
Push_32(reg_esp);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(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(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:
val=0;
E_Exit("CPU:8c:Illegal RM Byte");
}
if (rm >= 0xc0 ) {GetEArd;*eard=val;}
else {GetEAa;SaveMd(eaa,val);}
break;
}
CASE_D(0x8d) /* LEA Gd */
{
//Little hack to always use segprefixed version
core.seg_prefix_base=0;
GetRMrd;
if (TEST_PREFIX_ADDR) {
*rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])();
} else {
*rmrd=(Bit32u)(*GetEA_SEG[rm])();
}
break;
}
CASE_D(0x8f) /* POP Ed */
{
GetRM;
if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();}
else {GetEAa;SaveMd(eaa,Pop_32());}
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(0x9c) /* PUSHFD */
FillFlags();
Push_32(flags.word);
break;
CASE_D(0x9d) /* POPFD */
SETFLAGSd(Pop_32())
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Decode_Trap;
goto decode_end;
}
#endif
#ifdef 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 */
{
Bit16u addsp=Fetchw();
SETIP(Pop_32());reg_esp+=addsp;
break;
}
CASE_D(0xc3) /* RETN */
SETIP(Pop_32());
break;
CASE_D(0xc4) /* LES */
{
GetRMrd;GetEAa;
*rmrd=LoadMd(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+4));
break;
}
CASE_D(0xc5) /* LDS */
{
GetRMrd;GetEAa;
*rmrd=LoadMd(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+4));
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() & 0x1f;
Bitu frame_ptr=reg_esp-4;
if (cpu.stack.big) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_ebp-=4;reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
}
if (level) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
}
reg_esp-=bytes;
} else {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_bp-=4;reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
}
if (level) {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
}
reg_sp-=bytes;
}
reg_ebp=frame_ptr;
break;
}
CASE_D(0xc9) /* LEAVE */
reg_esp&=~cpu.stack.mask;
reg_esp|=(reg_ebp&cpu.stack.mask);
reg_ebp=Pop_32();
break;
CASE_D(0xca) /* RETF Iw */
{
if (CPU_RET(true,Fetchw())) {
LOADIP;
} else {
FillFlags();return CBRET_NONE;
}
break;
}
CASE_D(0xcb) /* RETF */
{
if (CPU_RET(true,0)) {
LOADIP;
} else {
FillFlags();return CBRET_NONE;
}
break;
}
CASE_D(0xcf) /* IRET */
{
if (CPU_IRET(true)) {
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Decode_Trap;
return CBRET_NONE;
}
#endif
#ifdef CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
#endif
//TODO TF check
goto decode_start;
} else return CBRET_NONE;
break;
}
CASE_D(0xd1) /* GRP2 Ed,1 */
GRP2D(1);break;
CASE_D(0xd3) /* GRP2 Ed,CL */
GRP2D(reg_cl);break;
CASE_D(0xe8) /* CALL Jd */
{
Bit32s newip=Fetchds();
Push_32((Bit32u)GETIP);
ADDIPd(newip);
break;
}
CASE_D(0xe9) /* JMP Jd */
ADDIPd(Fetchds());
break;
CASE_D(0xea) /* JMP Ad */
{
Bit32u newip=Fetchd();
Bit16u newcs=Fetchw();
SAVEIP;
if (CPU_JMP(true,newcs,newip)) {
LOADIP;
} else {
FillFlags();return CBRET_NONE;
}
break;
}
CASE_D(0xed) /* IN EAX,DX */
reg_eax=IO_Read(reg_dx) |
(IO_Read(reg_dx+1) << 8) |
(IO_Read(reg_dx+2) << 16) |
(IO_Read(reg_dx+3) << 24);
break;
CASE_D(0xef) /* OUT DX,EAX */
IO_Write(reg_dx,(Bit8u)(reg_eax>>0));
IO_Write(reg_dx+1,(Bit8u)(reg_eax>>8));
IO_Write(reg_dx+2,(Bit8u)(reg_eax>>16));
IO_Write(reg_dx+3,(Bit8u)(reg_eax>>24));
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 */
{
flags.type=t_NEGd;
if (rm >= 0xc0 ) {
GetEArd;flags.var1.d=*eard;flags.result.d=0-flags.var1.d;
*eard=flags.result.d;
} else {
GetEAa;flags.var1.d=LoadMd(eaa);flags.result.d=0-flags.var1.d;
SaveMd(eaa,flags.result.d);
}
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;Push_32(GETIP);SETIP(*eard);}
else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));}
break;
case 0x03: /* CALL FAR Ed */
{
GetEAa;
Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4);
SAVEIP;
if (CPU_CALL(true,newcs,newip)) {
LOADIP;
} else {
FillFlags();return CBRET_NONE;
}
}
break;
case 0x04: /* JMP NEAR Ed */
if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);}
else {GetEAa;SETIP(LoadMd(eaa));}
break;
case 0x05: /* JMP FAR Ed */
{
GetEAa;
Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4);
SAVEIP;
if (CPU_JMP(true,newcs,newip)) {
LOADIP;
} else {
FillFlags();return CBRET_NONE;
}
}
break;
case 0x06: /* Push Ed */
if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);}
else {GetEAa;Push_32(LoadMd(eaa));}
break;
default:
E_Exit("CPU:66:GRP5:Illegal call %2X",which);
break;
}
break;
}

View file

@ -0,0 +1,370 @@
/*
* Copyright (C) 2002 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 Library 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 */
{
GetRM;Bitu which=(rm>>3)&7;
switch (which) {
case 0x00: /* SLDT */
case 0x01: /* STR */
{
Bitu saveval;
if (!which) CPU_SLDT(saveval);
else CPU_STR(saveval);
if (rm >= 0xc0) {GetEArd;*eard=saveval;}
else {GetEAa;SaveMd(eaa,saveval);}
}
break;
case 0x02:case 0x03:case 0x04:case 0x05:
{
/* Just use 16-bit loads since were only using selectors */
FillFlags();
Bitu loadval;
if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
else {GetEAa;loadval=LoadMw(eaa);}
break;
switch (which) {
case 0x02:CPU_LLDT(loadval);break;
case 0x03:CPU_LTR(loadval);break;
case 0x04:CPU_VERR(loadval);break;
case 0x05:CPU_VERW(loadval);break;
}
}
default:
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
}
}
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,base;
switch (which) {
case 0x00: /* SGDT */
CPU_SGDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
break;
case 0x01: /* SIDT */
CPU_SIDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
break;
case 0x02: /* LGDT */
CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2));
break;
case 0x03: /* LIDT */
CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2));
break;
case 0x04: /* SMSW */
CPU_SMSW(limit);
SaveMw(eaa,limit);
break;
case 0x06: /* LMSW */
limit=LoadMw(eaa);
if (!CPU_LMSW(limit)) goto decode_end;
break;
}
} else {
GetEArw;Bitu limit;
switch (which) {
case 0x04: /* SMSW */
CPU_SMSW(limit);
*earw=limit;
break;
case 0x06: /* LMSW */
if (!CPU_LMSW(*earw)) goto decode_end;
break;
default:
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
break;
}
}
}
break;
CASE_0F_D(0x02) /* LAR Gd,Ed */
{
FillFlags();
GetRMrd;Bitu ar;
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 */
{
FillFlags();
GetRMrd;Bitu limit;
/* Just load 16-bit values for selectors */
if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit);
} else {
GetEAa;CPU_LSL(LoadMw(eaa),limit);
}
*rmrd=(Bit16u)limit;
}
break;
CASE_0F_D(0x80) /* JO */
JumpSId(get_OF());break;
CASE_0F_D(0x81) /* JNO */
JumpSId(!get_OF());break;
CASE_0F_D(0x82) /* JB */
JumpSId(get_CF());break;
CASE_0F_D(0x83) /* JNB */
JumpSId(!get_CF());break;
CASE_0F_D(0x84) /* JZ */
JumpSId(get_ZF());break;
CASE_0F_D(0x85) /* JNZ */
JumpSId(!get_ZF());break;
CASE_0F_D(0x86) /* JBE */
JumpSId(get_CF() || get_ZF());break;
CASE_0F_D(0x87) /* JNBE */
JumpSId(!get_CF() && !get_ZF());break;
CASE_0F_D(0x88) /* JS */
JumpSId(get_SF());break;
CASE_0F_D(0x89) /* JNS */
JumpSId(!get_SF());break;
CASE_0F_D(0x8a) /* JP */
JumpSId(get_PF());break;
CASE_0F_D(0x8b) /* JNP */
JumpSId(!get_PF());break;
CASE_0F_D(0x8c) /* JL */
JumpSId(get_SF() != get_OF());break;
CASE_0F_D(0x8d) /* JNL */
JumpSId(get_SF() == get_OF());break;
CASE_0F_D(0x8e) /* JLE */
JumpSId(get_ZF() || (get_SF() != get_OF()));break;
CASE_0F_D(0x8f) /* JNLE */
JumpSId((get_SF() == get_OF()) && !get_ZF());break;
CASE_0F_D(0xa0) /* PUSH FS */
Push_32(SegValue(fs));break;
CASE_0F_D(0xa1) /* POP FS */
CPU_SetSegGeneral(fs,(Bit16u)Pop_32());break;
CASE_0F_D(0xa3) /* BT Ed,Gd */
{
GetRMrd;
Bit32u mask=1 << (*rmrd & 31);
if (rm >= 0xc0 ) {
GetEArd;
SETFLAGBIT(CF,(*eard & mask));
} else {
GetEAa;Bit32u old=LoadMd(eaa);
SETFLAGBIT(CF,(old & mask));
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
break;
}
CASE_0F_D(0xa4) /* SHLD Ed,Gd,Ib */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;DSHLD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);}
else {GetEAa;DSHLD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);}
break;
}
CASE_0F_D(0xa8) /* PUSH GS */
Push_32(SegValue(gs));break;
CASE_0F_D(0xa9) /* POP GS */
CPU_SetSegGeneral(gs,(Bit16u)Pop_32());break;
CASE_0F_D(0xab) /* BTS Ed,Gd */
{
GetRMrd;
Bit32u mask=1 << (*rmrd & 31);
if (rm >= 0xc0 ) {
GetEArd;
SETFLAGBIT(CF,(*eard & mask));
*eard|=mask;
} else {
GetEAa;Bit32u old=LoadMd(eaa);
SETFLAGBIT(CF,(old & mask));
SaveMd(eaa,old | mask);
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
break;
}
CASE_0F_D(0xac) /* SHRD Ed,Gd,Ib */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);}
else {GetEAa;DSHRD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);}
break;
}
CASE_0F_D(0xad) /* SHRD Ed,Gd,Cl */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,reg_cl,LoadRd,SaveRd);}
else {GetEAa;DSHRD(eaa,*rmrd,reg_cl,LoadMd,SaveMd);}
break;
}
CASE_0F_D(0xb4) /* LFS Ed */
{
GetRMrd;GetEAa;
*rmrd=LoadMd(eaa);CPU_SetSegGeneral(fs,LoadMw(eaa+4));
break;
}
CASE_0F_D(0xb5) /* LGS Ed */
{
GetRMrd;GetEAa;
*rmrd=LoadMd(eaa);CPU_SetSegGeneral(gs,LoadMw(eaa+4));
break;
}
CASE_0F_D(0xb6) /* MOVZX Gd,Eb */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;}
else {GetEAa;*rmrd=LoadMb(eaa);}
break;
}
CASE_0F_D(0xaf) /* IMUL Gd,Ed */
{
RMGdEdOp3(DIMULD,*rmrd);
break;
}
CASE_0F_D(0xb2) /* LSS Ed */
{
GetRMrd;GetEAa;
*rmrd=LoadMd(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+4));
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 */
{
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);
}
}
if (flags.type!=t_CF) flags.prev_type=flags.type;
flags.type=t_CF;
break;
}
CASE_0F_D(0xbb) /* BTC Ed,Gd */
{
GetRMrd;
Bit32u mask=1 << (*rmrd & 31);
if (rm >= 0xc0 ) {
GetEArd;
SETFLAGBIT(CF,(*eard & mask));
*eard^=mask;
} else {
GetEAa;Bit32u old=LoadMd(eaa);
SETFLAGBIT(CF,(old & mask));
SaveMd(eaa,old ^ mask);
}
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
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;
}
flags.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 = 35; // Operandsize-1
while ((value & 0x80000000)==0) { result--; value<<=1; }
SETFLAGBIT(ZF,false);
*rmrd = result;
}
flags.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;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,243 @@
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;
if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base;
else si_base=SegBase(ds);
di_base=SegBase(es);
if (TEST_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 (!(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;
core.ip_lookup=core.op_start; //Reset IP to start of instruction
} else {
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
count_left=0;
}
}
add_index=GETFLAG(DF) ? -1 : 1;
if (count) switch (type) {
case R_OUTSB:
for (;count>0;count--) {
IO_Write(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_Write(reg_dx,LoadMb(si_base+si_index));
IO_Write(reg_dx+1,LoadMb(si_base+si_index+1));
si_index=(si_index+add_index) & add_mask;
}
break;
case R_OUTSD:
add_index<<=2;
for (;count>0;count--) {
IO_Write(reg_dx,LoadMb(si_base+si_index));
IO_Write(reg_dx+1,LoadMb(si_base+si_index+1));
IO_Write(reg_dx+2,LoadMb(si_base+si_index+2));
IO_Write(reg_dx+3,LoadMb(si_base+si_index+3));
si_index=(si_index+add_index) & add_mask;
}
break;
case R_INSB:
for (;count>0;count--) {
SaveMb(di_base+di_index,IO_Read(reg_dx));
di_index=(di_index+add_index) & add_mask;
}
break;
case R_INSW:
add_index<<=1;
for (;count>0;count--) {
SaveMb(di_base+di_index,IO_Read(reg_dx));
SaveMb(di_base+di_index+1,IO_Read(reg_dx+1));
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);
}
}

View file

@ -0,0 +1,138 @@
/*
* Copyright (C) 2002 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 Library 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 SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_)
#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs))
#define SAVEIP {reg_eip=GETIP;}
#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);}
#define LEAVECORE \
SAVEIP; \
FillFlags();
static INLINE void ADDIPw(Bits add) {
SAVEIP;
reg_eip=(Bit16u)(reg_eip+add);
LOADIP;
}
static INLINE void ADDIPd(Bits add) {
SAVEIP;
reg_eip=(reg_eip+add);
LOADIP;
}
static INLINE void ADDIPFAST(Bits blah) {
core.ip_lookup+=blah;
}
#define EXCEPTION(blah) \
{ \
Bit8u new_num=blah; \
core.ip_lookup=core.op_start; \
LEAVECORE; \
if (Interrupt(new_num)) { \
goto decode_start; \
} else return CBRET_NONE; \
}
static INLINE Bit8u Fetchb() {
Bit8u temp=LoadMb(core.ip_lookup);
core.ip_lookup+=1;
return temp;
}
static INLINE Bit16u Fetchw() {
Bit16u temp=LoadMw(core.ip_lookup);
core.ip_lookup+=2;
return temp;
}
static INLINE Bit32u Fetchd() {
Bit32u temp=LoadMd(core.ip_lookup);
core.ip_lookup+=4;
return temp;
}
static INLINE Bit8s Fetchbs() {
return Fetchb();
}
static INLINE Bit16s Fetchws() {
return Fetchw();
}
static INLINE Bit32s Fetchds() {
return Fetchd();
}
static INLINE void Push_16(Bit16u blah) {
reg_esp-=2;
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
};
static INLINE void Push_32(Bit32u blah) {
reg_esp-=4;
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
};
static INLINE Bit16u Pop_16() {
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=2;
return temp;
};
static INLINE Bit32u Pop_32() {
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=4;
return temp;
};
#define JumpSIb(blah) \
if (blah) { \
ADDIPFAST(Fetchbs()); \
} else { \
ADDIPFAST(1); \
}
#define JumpSIw(blah) \
if (blah) { \
ADDIPw(Fetchws()); \
} else { \
ADDIPFAST(2); \
}
#define JumpSId(blah) \
if (blah) { \
ADDIPd(Fetchds()); \
} else { \
ADDIPFAST(4); \
}
#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"

View file

@ -0,0 +1,356 @@
/*
* Copyright (C) 2002 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 Library 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 (*GetEATable[256])(void);
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 SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); }
static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); }
static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());}
static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); }
static PhysPt EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); }
static PhysPt EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); }
static GetEATable GetEA_NONE={
/* 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
};
static PhysPt EA_16_00_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static PhysPt EA_16_01_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static PhysPt EA_16_02_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static PhysPt EA_16_03_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si); }
static PhysPt EA_16_05_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di); }
static PhysPt EA_16_06_s(void) { return core.seg_prefix_base+(Bit16u)(Fetchw()); }
static PhysPt EA_16_07_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx); }
static PhysPt EA_16_40_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_41_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_42_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_43_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_44_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchbs()); }
static PhysPt EA_16_80_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_81_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_82_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_83_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_84_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchws()); }
static GetEATable GetEA_SEG={
/* 00 */
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
/* 01 */
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
/* 10 */
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
/* 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
};
static Bit32u SIBZero=0;
static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi };
INLINE PhysPt Sib(Bitu mode) {
Bit8u sib=Fetchb();
PhysPt base;
switch (sib&7) {
case 0: /* EAX Base */
base=SegBase(ds)+reg_eax;break;
case 1: /* ECX Base */
base=SegBase(ds)+reg_ecx;break;
case 2: /* EDX Base */
base=SegBase(ds)+reg_edx;break;
case 3: /* EBX Base */
base=SegBase(ds)+reg_ebx;break;
case 4: /* ESP Base */
base=SegBase(ss)+reg_esp;break;
case 5: /* #1 Base */
if (!mode) {
base=SegBase(ds)+Fetchd();break;
} else {
base=SegBase(ss)+reg_ebp;break;
}
case 6: /* ESI Base */
base=SegBase(ds)+reg_esi;break;
case 7: /* EDI Base */
base=SegBase(ds)+reg_edi;break;
}
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
return base;
};
static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; }
static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; }
static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; }
static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; }
static PhysPt EA_32_04_n(void) { return Sib(0);}
static PhysPt EA_32_05_n(void) { return SegBase(ds)+Fetchd(); }
static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; }
static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; }
static PhysPt EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); }
static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); }
static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); }
static PhysPt EA_32_43_n(void) { return SegBase(ds)+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 SegBase(ss)+reg_ebp+Fetchbs(); }
static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); }
static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); }
static PhysPt EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); }
static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); }
static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); }
static PhysPt EA_32_83_n(void) { return SegBase(ds)+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 SegBase(ss)+reg_ebp+Fetchds(); }
static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); }
static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); }
static GetEATable GetEA_ADDR={
/* 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
};
INLINE PhysPt Sib_s(Bitu mode) {
Bit8u sib=Fetchb();
PhysPt base;
switch (sib&7) {
case 0: /* EAX Base */
base=reg_eax;break;
case 1: /* ECX Base */
base=reg_ecx;break;
case 2: /* EDX Base */
base=reg_edx;break;
case 3: /* EBX Base */
base=reg_ebx;break;
case 4: /* ESP Base */
base=reg_esp;break;
case 5: /* #1 Base */
if (!mode) {
base=Fetchd();break;
} else {
base=reg_ebp;break;
}
case 6: /* ESI Base */
base=reg_esi;break;
case 7: /* EDI Base */
base=reg_edi;break;
}
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
return base;
};
static PhysPt EA_32_00_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax); }
static PhysPt EA_32_01_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx); }
static PhysPt EA_32_02_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx); }
static PhysPt EA_32_03_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx); }
static PhysPt EA_32_04_s(void) { return core.seg_prefix_base+(Bit32u)(Sib_s(0));}
static PhysPt EA_32_05_s(void) { return core.seg_prefix_base+(Bit32u)(Fetchd()); }
static PhysPt EA_32_06_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi); }
static PhysPt EA_32_07_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi); }
static PhysPt EA_32_40_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchbs()); }
static PhysPt EA_32_41_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchbs()); }
static PhysPt EA_32_42_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchbs()); }
static PhysPt EA_32_43_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchbs()); }
static PhysPt EA_32_44_s(void) { PhysPt temp=Sib_s(1);return core.seg_prefix_base+(Bit32u)(temp+Fetchbs());}
static PhysPt EA_32_45_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchbs()); }
static PhysPt EA_32_46_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchbs()); }
static PhysPt EA_32_47_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchbs()); }
static PhysPt EA_32_80_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchds()); }
static PhysPt EA_32_81_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchds()); }
static PhysPt EA_32_82_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchds()); }
static PhysPt EA_32_83_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchds()); }
static PhysPt EA_32_84_s(void) { PhysPt temp=Sib_s(2);return core.seg_prefix_base+(Bit32u)(temp+Fetchds());}
static PhysPt EA_32_85_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchds()); }
static PhysPt EA_32_86_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchds()); }
static PhysPt EA_32_87_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchds()); }
static GetEATable GetEA_SEG_ADDR={
/* 00 */
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
/* 01 */
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
/* 10 */
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
/* 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_SEG) { \
if (TEST_PREFIX_ADDR) { \
eaa=core.seg_prefix_base+Fetchd(); \
} else { \
eaa=core.seg_prefix_base+Fetchw(); \
} \
} else { \
if (TEST_PREFIX_ADDR) { \
eaa=SegBase(ds)+Fetchd(); \
} else { \
eaa=SegBase(ds)+Fetchw(); \
} \
}

View file

@ -44,14 +44,19 @@ CPU_Decoder * cpudecoder;
void CPU_Real_16_Slow_Start(bool big);
void CPU_Core_Full_Start(bool big);
void CPU_Core_Insane_Start(bool big);
void CPU_Core_Normal_Start(bool big);
#if 1
typedef void DecoderStart(void);
#define realcore_start CPU_Core_Normal_Start
#define pmodecore_start CPU_Core_Normal_Start
#define realcore_start CPU_Real_16_Slow_Start
//#define realcore_start CPU_Core_Insane_Start
//#define realcore_start CPU_Core_Full_Start
#else
#define realcore_start CPU_Core_Full_Start
#define pmodecore_start CPU_Core_Full_Start
#endif
void CPU_Push16(Bitu value) {
reg_esp-=2;
@ -86,7 +91,7 @@ PhysPt SelBase(Bitu sel) {
}
void CPU_SetFlags(Bitu word) {
flags.word=(word|2)&~0x14;
flags.word=(word|2)&~0x28;
}
bool CPU_CheckCodeType(CODE_TYPE type) {
@ -97,10 +102,10 @@ bool CPU_CheckCodeType(CODE_TYPE type) {
realcore_start(false);
break;
case CODE_PMODE16:
CPU_Core_Full_Start(false);
pmodecore_start(false);
break;
case CODE_PMODE32:
CPU_Core_Full_Start(true);
pmodecore_start(true);
break;
}
return false;
@ -272,7 +277,7 @@ bool CPU_IRET(bool use32) {
Segs.val[cs]=(selector & 0xfffc) | cpu.cpl;;
reg_eip=offset;
CPU_SetFlags(old_flags);
LOG_MSG("IRET:Same level return to %X:%X",selector,offset);
LOG_MSG("IRET:Same level return to %X:%X big %d",selector,offset,cpu.code.big);
} else {
/* Return to higher privilege */
switch (desc.Type()) {
@ -303,7 +308,7 @@ bool CPU_IRET(bool use32) {
reg_esp=new_esp;
CPU_SetSegGeneral(ss,new_ss);
//TODO Maybe validate other segments, but why would anyone use them?
LOG_MSG("IRET:Outer level return to %X:%X",selector,offset);
LOG_MSG("IRET:Outer level return to %X:X big %d",selector,offset,cpu.code.big);
}
return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16);
}
@ -329,11 +334,11 @@ bool CPU_JMP(bool use32,Bitu selector,Bitu offset) {
if (rpl>cpu.cpl) E_Exit("JMP:NC:RPL>CPL");
if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
cpu.cpl=desc.DPL();
LOG_MSG("JMP:Code:NC to %X:%X",selector,offset);
LOG_MSG("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_MSG("JMP:Code:C to %X:%X",selector,offset);
LOG_MSG("JMP:Code:C to %X:%X big %d",selector,offset,desc.Big());
CODE_jmp:
/* Normal jump to another selector:offset */
Segs.phys[cs]=desc.GetBase();
@ -524,7 +529,6 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
cpu.pmode=true;
LOG_MSG("Protected mode");
PAGING_Enable((value & CR0_PAGING)>0);
CPU_Core_Full_Start(cpu.code.big);
} else {
cpu.pmode=false;
PAGING_Enable(false);
@ -578,6 +582,7 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
void CPU_LAR(Bitu selector,Bitu & ar) {
Descriptor desc;Bitu rpl=selector & 3;
ar=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
return;
@ -625,6 +630,7 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
void CPU_LSL(Bitu selector,Bitu & limit) {
Descriptor desc;Bitu rpl=selector & 3;
limit=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
return;