diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index b485ebed..6eee8926 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -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 \ No newline at end of file + paging.cpp lazyflags.h core_normal.cpp \ No newline at end of file diff --git a/src/cpu/core_normal.cpp b/src/cpu/core_normal.cpp new file mode 100644 index 00000000..73522a22 --- /dev/null +++ b/src/cpu/core_normal.cpp @@ -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; + } +} + diff --git a/src/cpu/core_normal/Makefile.am b/src/cpu/core_normal/Makefile.am new file mode 100644 index 00000000..99f76f3d --- /dev/null +++ b/src/cpu/core_normal/Makefile.am @@ -0,0 +1,3 @@ + +noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \ + prefix_66_0f.h string.h diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h new file mode 100644 index 00000000..6a30e052 --- /dev/null +++ b/src/cpu/core_normal/helpers.h @@ -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); \ + } \ +} + diff --git a/src/cpu/core_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h new file mode 100644 index 00000000..0871fab1 --- /dev/null +++ b/src/cpu/core_normal/prefix_0f.h @@ -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; + diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h new file mode 100644 index 00000000..7f769ef5 --- /dev/null +++ b/src/cpu/core_normal/prefix_66.h @@ -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>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; + } + + diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h new file mode 100644 index 00000000..d24ebc8a --- /dev/null +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -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; + } diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h new file mode 100644 index 00000000..0e40cd8c --- /dev/null +++ b/src/cpu/core_normal/prefix_none.h @@ -0,0 +1,1171 @@ +/* + * 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_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 */ + CPU_SetSegGeneral(es,Pop_16());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 */ + CPU_SetSegGeneral(ss,Pop_16());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 */ + CPU_SetSegGeneral(ds,Pop_16());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 */ +//TODO Check if this is correct i think it's SP+2 or something + 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 */ + { + FillFlags(); + 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^=OPCODE_SIZE; + 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 */ + DoString(R_INSB);break; + CASE_W(0x6d) /* INSW */ + DoString(R_INSW);break; + CASE_B(0x6e) /* OUTSB */ + DoString(R_OUTSB);break; + CASE_W(0x6f) /* OUTSW */ + DoString(R_OUTSW);break; + CASE_B(0x70) /* JO */ + JumpSIb(get_OF());break; + CASE_B(0x71) /* JNO */ + JumpSIb(!get_OF());break; + CASE_B(0x72) /* JB */ + JumpSIb(get_CF());break; + CASE_B(0x73) /* JNB */ + JumpSIb(!get_CF());break; + CASE_B(0x74) /* JZ */ + JumpSIb(get_ZF());break; + CASE_B(0x75) /* JNZ */ + JumpSIb(!get_ZF());break; + CASE_B(0x76) /* JBE */ + JumpSIb(get_CF() || get_ZF());break; + CASE_B(0x77) /* JNBE */ + JumpSIb(!get_CF() && !get_ZF());break; + CASE_B(0x78) /* JS */ + JumpSIb(get_SF());break; + CASE_B(0x79) /* JNS */ + JumpSIb(!get_SF());break; + CASE_B(0x7a) /* JP */ + JumpSIb(get_PF());break; + CASE_B(0x7b) /* JNP */ + JumpSIb(!get_PF());break; + CASE_B(0x7c) /* JL */ + JumpSIb(get_SF() != get_OF());break; + CASE_B(0x7d) /* JNL */ + JumpSIb(get_SF() == get_OF());break; + CASE_B(0x7e) /* JLE */ + JumpSIb(get_ZF() || (get_SF() != get_OF()));break; + CASE_B(0x7f) /* JNLE */ + JumpSIb((get_SF() == get_OF()) && !get_ZF());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 {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: + val=0; + E_Exit("CPU:8c:Illegal RM Byte"); + } + if (rm >= 0xc0 ) {GetEArw;*earw=val;} + else {GetEAa;SaveMw(eaa,val);} + break; + } + CASE_W(0x8d) /* LEA Gw */ + { + //Little hack to always use segprefixed version + core.seg_prefix_base=0; + GetRMrw; + if (TEST_PREFIX_ADDR) { + *rmrw=(Bit16u)(*GetEA_SEG_ADDR[rm])(); + } else { + *rmrw=(Bit16u)(*GetEA_SEG[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 0x00: /* MOV ES,Ew */ + CPU_SetSegGeneral(es,val);break; + case 0x01: /* MOV CS,Ew Illegal*/ + E_Exit("CPU:Illegal MOV CS Call"); + break; + case 0x02: /* MOV SS,Ew */ + CPU_SetSegGeneral(ss,val); + break; + case 0x03: /* MOV DS,Ew */ + CPU_SetSegGeneral(ds,val);break; + case 0x04: /* MOV FS,Ew */ + CPU_SetSegGeneral(fs,val);break; + case 0x05: /* MOV GS,Ew */ + CPU_SetSegGeneral(gs,val);break; + default: + E_Exit("CPU:8E:Illegal RM Byte"); + } + break; + } + CASE_W(0x8f) /* POP Ew */ + { + GetRM; + if (rm >= 0xc0 ) {GetEArw;*earw=Pop_16();} + else {GetEAa;SaveMw(eaa,Pop_16());} + 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 */ + { + Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); + SAVEIP; + if (CPU_CALL(false,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + break; + } + CASE_B(0x9b) /* WAIT */ + break; /* No waiting here */ + CASE_W(0x9c) /* PUSHF */ + FillFlags(); + Push_16(flags.word); + break; + CASE_W(0x9d) /* POPF */ + SETFLAGSw(Pop_16()); +#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_B(0x9e) /* SAHF */ + SETFLAGSb(reg_ah); + break; + CASE_B(0x9f) /* LAHF */ + FillFlags(); + reg_ah=flags.word&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 */ + { + Bit16u addsp=Fetchw(); + SETIP(Pop_16());reg_esp+=addsp; + break; + } + CASE_W(0xc3) /* RETN */ + SETIP(Pop_16()); + break; + CASE_W(0xc4) /* LES */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+2)); + break; + } + CASE_W(0xc5) /* LDS */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+2)); + 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() & 0x1f; + Bitu frame_ptr=reg_esp-2; + if (cpu.stack.big) { + reg_esp-=2; + mem_writew(SegBase(ss)+reg_esp,reg_bp); + for (Bitu i=1;i>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 */ + { + flags.type=t_NEGb; + if (rm >= 0xc0 ) { + GetEArb;flags.var1.b=*earb;flags.result.b=0-flags.var1.b; + *earb=flags.result.b; + } else { + GetEAa;flags.var1.b=LoadMb(eaa);flags.result.b=0-flags.var1.b; + SaveMb(eaa,flags.result.b); + } + 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 */ + { + flags.type=t_NEGw; + if (rm >= 0xc0 ) { + GetEArw;flags.var1.w=*earw;flags.result.w=0-flags.var1.w; + *earw=flags.result.w; + } else { + GetEAa;flags.var1.w=LoadMw(eaa);flags.result.w=0-flags.var1.w; + SaveMw(eaa,flags.result.w); + } + 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 */ + SETFLAGBIT(CF,false); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + CASE_B(0xf9) /* STC */ + SETFLAGBIT(CF,true); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + CASE_B(0xfa) /* CLI */ + SETFLAGBIT(IF,false); + break; + CASE_B(0xfb) /* STI */ + SETFLAGBIT(IF,true); +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif + break; + CASE_B(0xfc) /* CLD */ + SETFLAGBIT(DF,false); + break; + CASE_B(0xfd) /* STD */ + SETFLAGBIT(DF,true); + 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(); + LEAVECORE; + 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;Push_16((Bit16u)GETIP);SETIP(*earw);} + else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));} + break; + case 0x03: /* CALL Ep */ + { + GetEAa; + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SAVEIP; + if (CPU_CALL(false,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + } + break; + case 0x04: /* JMP Ev */ + if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} + else {GetEAa;SETIP(LoadMw(eaa));} + break; + case 0x05: /* JMP Ep */ + { + GetEAa; + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SAVEIP; + if (CPU_JMP(false,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } } + break; + case 0x06: /* PUSH Ev */ + if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} + else {GetEAa;Push_16(LoadMw(eaa));} + break; + default: + E_Exit("CPU:GRP5:Illegal Call %2X",which); + break; + } + break; + } + + + + diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h new file mode 100644 index 00000000..524025f4 --- /dev/null +++ b/src/cpu/core_normal/string.h @@ -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) && (type0;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); + } +} \ No newline at end of file diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h new file mode 100644 index 00000000..d0e4d2a1 --- /dev/null +++ b/src/cpu/core_normal/support.h @@ -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" + + diff --git a/src/cpu/core_normal/table_ea.h b/src/cpu/core_normal/table_ea.h new file mode 100644 index 00000000..a93182e4 --- /dev/null +++ b/src/cpu/core_normal/table_ea.h @@ -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]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_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(); \ + } \ + } + + diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index c44dcd7a..5e7662af 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -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;