Changes to cpu cores.
Save/Load eip after each opcode Handle IO exceptions Handle protection exception for protected opcodes with too less privilege Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1773
This commit is contained in:
parent
2bccfd7a22
commit
5460def634
18 changed files with 589 additions and 742 deletions
|
@ -52,7 +52,6 @@ void CPU_SLDT(Bitu & selector);
|
|||
void CPU_SIDT(Bitu & limit,Bitu & base);
|
||||
void CPU_SGDT(Bitu & limit,Bitu & base);
|
||||
|
||||
|
||||
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
|
||||
void CPU_LAR(Bitu selector,Bitu & ar);
|
||||
void CPU_LSL(Bitu selector,Bitu & limit);
|
||||
|
@ -61,37 +60,43 @@ bool CPU_SET_CRX(Bitu cr,Bitu value);
|
|||
Bitu CPU_GET_CRX(Bitu cr);
|
||||
|
||||
void CPU_SMSW(Bitu & word);
|
||||
bool CPU_LMSW(Bitu word);
|
||||
Bitu CPU_LMSW(Bitu word);
|
||||
|
||||
void CPU_VERR(Bitu selector);
|
||||
void CPU_VERW(Bitu selector);
|
||||
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen);
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen);
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu opLen);
|
||||
void CPU_IRET(bool use32,Bitu opLen);
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip);
|
||||
void CPU_IRET(bool use32,Bitu oldeip);
|
||||
void CPU_HLT(Bitu oldeip);
|
||||
|
||||
bool CPU_CLI(Bitu opLen);
|
||||
bool CPU_STI(Bitu opLen);
|
||||
bool CPU_POPF(Bitu use32);
|
||||
bool CPU_PUSHF(Bitu use32);
|
||||
bool CPU_CLI(void);
|
||||
bool CPU_STI(void);
|
||||
|
||||
bool CPU_IO_Exception(Bitu port,Bitu size);
|
||||
void CPU_RunException(void);
|
||||
|
||||
void CPU_ENTER(bool use32,Bitu bytes,Bitu level);
|
||||
|
||||
#define CPU_INT_SOFTWARE 0x1
|
||||
#define CPU_INT_EXCEPTION 0x2
|
||||
#define CPU_INT_HAS_ERROR 0x4
|
||||
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0);
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip);
|
||||
INLINE void CPU_HW_Interrupt(Bitu num) {
|
||||
CPU_Interrupt(num,0);
|
||||
CPU_Interrupt(num,0,reg_eip);
|
||||
}
|
||||
INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) {
|
||||
CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen);
|
||||
INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) {
|
||||
CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip);
|
||||
}
|
||||
|
||||
void CPU_Exception(Bitu which,Bitu error=0);
|
||||
void CPU_StartException(void);
|
||||
void CPU_SetupException(Bitu which,Bitu error=0);
|
||||
|
||||
bool CPU_SetSegGeneral(SegNames seg,Bitu value);
|
||||
void CPU_HLT(Bitu opLen);
|
||||
bool CPU_PopSeg(SegNames seg,bool use32);
|
||||
|
||||
void CPU_CPUID(void);
|
||||
Bitu CPU_Pop16(void);
|
||||
|
|
|
@ -54,47 +54,28 @@ typedef PhysPt EAPoint;
|
|||
#include "core_full/optable.h"
|
||||
#include "instructions.h"
|
||||
|
||||
#define LEAVECORE \
|
||||
SaveIP(); \
|
||||
FillFlags();
|
||||
|
||||
#define EXCEPTION(blah) \
|
||||
{ \
|
||||
Bit8u new_num=blah; \
|
||||
IPPoint=inst.opcode_start; \
|
||||
LEAVECORE; \
|
||||
CPU_Exception(new_num,0); \
|
||||
LoadIP(); \
|
||||
goto nextopcode; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
Bits CPU_Core_Full_Run(void) {
|
||||
FullData inst;
|
||||
restart_core:
|
||||
if (!cpu.code.big) {
|
||||
inst.start_prefix=0x0;;
|
||||
inst.start_entry=0x0;
|
||||
} else {
|
||||
inst.start_prefix=PREFIX_ADDR;
|
||||
inst.start_entry=0x200;
|
||||
}
|
||||
EAPoint IPPoint;
|
||||
LoadIP();
|
||||
lflags.type=t_UNKNOWN;
|
||||
while (CPU_Cycles-->0) {
|
||||
#if C_DEBUG
|
||||
cycle_count++;
|
||||
#if C_HEAVY_DEBUG
|
||||
SaveIP();
|
||||
if (DEBUG_HeavyIsBreakpoint()) {
|
||||
LEAVECORE;
|
||||
return debugCallback;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
inst.opcode_start=IPPoint;
|
||||
inst.entry=inst.start_entry;
|
||||
inst.prefix=inst.start_prefix;
|
||||
LoadIP();
|
||||
inst.entry=cpu.code.big*0x200;
|
||||
inst.prefix=cpu.code.big;
|
||||
restartopcode:
|
||||
inst.entry=(inst.entry & 0xffffff00) | Fetchb();
|
||||
inst.code=OpCodeTable[inst.entry];
|
||||
|
@ -102,14 +83,14 @@ restartopcode:
|
|||
#include "core_full/op.h"
|
||||
#include "core_full/save.h"
|
||||
nextopcode:;
|
||||
}
|
||||
LEAVECORE;
|
||||
return CBRET_NONE;
|
||||
SaveIP();
|
||||
continue;
|
||||
illegalopcode:
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_Exception(0x6,0);
|
||||
goto restart_core;
|
||||
LOG_MSG("Illegal opcode");
|
||||
CPU_Exception(0x6,0);
|
||||
}
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -144,18 +144,12 @@ l_M_Ed:
|
|||
inst.op1.d=SegValue((SegNames)inst.rm_index);
|
||||
break;
|
||||
case M_Efw:
|
||||
if (inst.rm>=0xC0) {
|
||||
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
|
||||
goto nextopcode;
|
||||
}
|
||||
if (inst.rm>=0xc0) goto illegalopcode;
|
||||
inst.op1.d=LoadMw(inst.rm_eaa);
|
||||
inst.op2.d=LoadMw(inst.rm_eaa+2);
|
||||
break;
|
||||
case M_Efd:
|
||||
if (inst.rm>=0xc0) {
|
||||
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
|
||||
goto nextopcode;
|
||||
}
|
||||
if (inst.rm>=0xc0) goto illegalopcode;
|
||||
inst.op1.d=LoadMd(inst.rm_eaa);
|
||||
inst.op2.d=LoadMw(inst.rm_eaa+4);
|
||||
break;
|
||||
|
@ -183,8 +177,6 @@ l_M_Ed:
|
|||
inst.op2.d=1;
|
||||
inst.code=Groups[inst.code.op][inst.rm_index];
|
||||
goto l_MODRMswitch;
|
||||
|
||||
/* Should continue with normal handler afterwards */
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
|
@ -206,30 +198,6 @@ l_M_Ed:
|
|||
inst.op1.d = Pop_32();
|
||||
inst.op2.d = Pop_16();
|
||||
break;
|
||||
case L_PFLGw:
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=IPPoint-inst.opcode_start;
|
||||
CPU_Exception(13,0);
|
||||
goto restart_core;
|
||||
}
|
||||
SETFLAGSw(Pop_16());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
break;
|
||||
case L_PFLGd:
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=IPPoint-inst.opcode_start;
|
||||
CPU_Exception(13,0);
|
||||
goto restart_core;
|
||||
}
|
||||
SETFLAGSd(Pop_32());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
break;
|
||||
case L_Ib:
|
||||
inst.op1.d=Fetchb();
|
||||
break;
|
||||
|
@ -270,9 +238,6 @@ l_M_Ed:
|
|||
case L_REGd:
|
||||
inst.op1.d=reg_32(inst.code.extra);
|
||||
break;
|
||||
case L_FLG:
|
||||
inst.op1.d = FillFlags();
|
||||
break;
|
||||
case L_SEG:
|
||||
inst.op1.d=SegValue((SegNames)inst.code.extra);
|
||||
break;
|
||||
|
@ -306,10 +271,10 @@ l_M_Ed:
|
|||
inst.repz=true;
|
||||
goto restartopcode;
|
||||
case L_PREOP:
|
||||
inst.entry=inst.start_entry ^ 0x200;
|
||||
inst.entry=(cpu.code.big ^1) * 0x200;
|
||||
goto restartopcode;
|
||||
case L_PREADD:
|
||||
inst.prefix^=PREFIX_ADDR;
|
||||
inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1);
|
||||
goto restartopcode;
|
||||
case L_VAL:
|
||||
inst.op1.d=inst.code.extra;
|
||||
|
@ -319,41 +284,40 @@ l_M_Ed:
|
|||
inst.op1.d=4;
|
||||
break;
|
||||
case D_IRETw:
|
||||
LEAVECORE;
|
||||
CPU_IRET(false,IPPoint-inst.opcode_start);
|
||||
FillFlags();
|
||||
CPU_IRET(false,GetIP());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto restart_core;
|
||||
continue;
|
||||
case D_IRETd:
|
||||
LEAVECORE;
|
||||
CPU_IRET(true,IPPoint-inst.opcode_start);
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
FillFlags();
|
||||
CPU_IRET(true,GetIP());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck)
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto restart_core;
|
||||
continue;
|
||||
case D_RETFwIw:
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(false,words,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(false,words,GetIP());
|
||||
continue;
|
||||
}
|
||||
case D_RETFw:
|
||||
LEAVECORE;
|
||||
CPU_RET(false,0,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(false,0,GetIP());
|
||||
continue;
|
||||
case D_RETFdIw:
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(true,words,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(true,words,GetIP());
|
||||
continue;
|
||||
}
|
||||
case D_RETFd:
|
||||
LEAVECORE;
|
||||
CPU_RET(true,0,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(true,0,GetIP());
|
||||
continue;
|
||||
/* Direct operations */
|
||||
case L_STRING:
|
||||
#include "string.h"
|
||||
|
@ -381,18 +345,10 @@ l_M_Ed:
|
|||
reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
|
||||
goto nextopcode;
|
||||
case D_POPSEGw:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2;
|
||||
CPU_StartException();goto restart_core;
|
||||
}
|
||||
if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
|
||||
goto nextopcode;
|
||||
case D_POPSEGd:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4;
|
||||
CPU_StartException();goto restart_core;
|
||||
}
|
||||
if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
|
||||
goto nextopcode;
|
||||
case D_SETALC:
|
||||
reg_al = get_CF() ? 0xFF : 0;
|
||||
|
@ -427,14 +383,10 @@ l_M_Ed:
|
|||
else reg_edx=0;
|
||||
goto nextopcode;
|
||||
case D_CLI:
|
||||
LEAVECORE;
|
||||
if (CPU_CLI(IPPoint-inst.opcode_start))
|
||||
goto restart_core;
|
||||
if (CPU_CLI()) RunException();
|
||||
goto nextopcode;
|
||||
case D_STI:
|
||||
LEAVECORE;
|
||||
if (CPU_STI(IPPoint-inst.opcode_start))
|
||||
goto restart_core;
|
||||
if (CPU_STI()) RunException();
|
||||
goto nextopcode;
|
||||
case D_STC:
|
||||
FillFlags();SETFLAGBIT(CF,true);
|
||||
|
@ -454,71 +406,40 @@ l_M_Ed:
|
|||
SETFLAGBIT(DF,true);
|
||||
cpu.direction=-1;
|
||||
goto nextopcode;
|
||||
case D_PUSHF:
|
||||
FillFlags();
|
||||
if (CPU_PUSHF(inst.code.extra)) RunException();
|
||||
goto nextopcode;
|
||||
case D_POPF:
|
||||
if (CPU_POPF(inst.code.extra)) RunException();
|
||||
lflags.type=t_UNKNOWN;
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto nextopcode;
|
||||
case D_SAHF:
|
||||
SETFLAGSb(reg_ah);
|
||||
goto nextopcode;
|
||||
case D_LAHF:
|
||||
FillFlags();
|
||||
reg_ah=reg_flags&0xff;
|
||||
goto nextopcode;
|
||||
case D_WAIT:
|
||||
case D_NOP:
|
||||
goto nextopcode;
|
||||
case D_ENTERw:
|
||||
{
|
||||
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<level;i++) {
|
||||
reg_ebp-=2;reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=2;reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_bp=frame_ptr;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(false,bytes,level);
|
||||
goto nextopcode;
|
||||
}
|
||||
case D_ENTERd:
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-4;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=4;reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=4;reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_ebp=frame_ptr;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(true,bytes,level);
|
||||
goto nextopcode;
|
||||
}
|
||||
case D_LEAVEw:
|
||||
|
@ -547,8 +468,8 @@ l_M_Ed:
|
|||
CPU_CPUID();
|
||||
goto nextopcode;
|
||||
case D_HLT:
|
||||
LEAVECORE;
|
||||
CPU_HLT(IPPoint-inst.opcode_start);
|
||||
FillFlags();
|
||||
CPU_HLT(GetIP());
|
||||
return CBRET_NONE;
|
||||
case D_CLTS:
|
||||
//TODO Really clear it sometime
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#define SaveIP() reg_eip=(Bit32u)(IPPoint-SegBase(cs));
|
||||
#define LoadIP() IPPoint=SegBase(cs)+reg_eip;
|
||||
#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));
|
||||
#define LoadIP() inst.cseip=SegBase(cs)+reg_eip;
|
||||
#define GetIP() (inst.cseip-SegBase(cs))
|
||||
|
||||
#define RunException() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
static INLINE Bit8u the_Fetchb(EAPoint & loc) {
|
||||
Bit8u temp=LoadMb(loc);
|
||||
|
@ -19,42 +25,16 @@ static INLINE Bit32u the_Fetchd(EAPoint & loc) {
|
|||
return temp;
|
||||
}
|
||||
|
||||
#define Fetchb() the_Fetchb(IPPoint)
|
||||
#define Fetchw() the_Fetchw(IPPoint)
|
||||
#define Fetchd() the_Fetchd(IPPoint)
|
||||
#define Fetchb() the_Fetchb(inst.cseip)
|
||||
#define Fetchw() the_Fetchw(inst.cseip)
|
||||
#define Fetchd() the_Fetchd(inst.cseip)
|
||||
|
||||
#define Fetchbs() (Bit8s)the_Fetchb(IPPoint)
|
||||
#define Fetchws() (Bit16s)the_Fetchw(IPPoint)
|
||||
#define Fetchds() (Bit32s)the_Fetchd(IPPoint)
|
||||
|
||||
#if 0
|
||||
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(void) {
|
||||
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static INLINE Bit32u Pop_32(void) {
|
||||
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=4;
|
||||
return temp;
|
||||
}
|
||||
|
||||
#else
|
||||
#define Fetchbs() (Bit8s)the_Fetchb(inst.cseip)
|
||||
#define Fetchws() (Bit16s)the_Fetchw(inst.cseip)
|
||||
#define Fetchds() (Bit32s)the_Fetchd(inst.cseip)
|
||||
|
||||
#define Push_16 CPU_Push16
|
||||
#define Push_32 CPU_Push32
|
||||
#define Pop_16 CPU_Pop16
|
||||
#define Pop_32 CPU_Pop32
|
||||
|
||||
#endif
|
||||
|
|
|
@ -322,51 +322,57 @@ switch (inst.code.op) {
|
|||
Push_32(reg_eip);
|
||||
break;
|
||||
case O_CALLFw:
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,inst.op2.d,inst.op1.d,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_CALL(false,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_CALLFd:
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,inst.op2.d,inst.op1.d,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_CALL(true,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_JMPFw:
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,inst.op2.d,inst.op1.d,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_JMP(false,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_JMPFd:
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,inst.op2.d,inst.op1.d,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_JMP(true,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_INT:
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint())
|
||||
return debugCallback;
|
||||
else if (DEBUG_IntBreakpoint(inst.op1.b))
|
||||
return debugCallback;
|
||||
#endif
|
||||
CPU_SW_Interrupt(inst.op1.b,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
CPU_SW_Interrupt(inst.op1.b,GetIP());
|
||||
continue;
|
||||
case O_INb:
|
||||
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
|
||||
reg_al=IO_ReadB(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_INw:
|
||||
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
|
||||
reg_ax=IO_ReadW(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_INd:
|
||||
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
|
||||
reg_eax=IO_ReadD(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_OUTb:
|
||||
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
|
||||
IO_WriteB(inst.op1.d,reg_al);
|
||||
goto nextopcode;
|
||||
case O_OUTw:
|
||||
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
|
||||
IO_WriteW(inst.op1.d,reg_ax);
|
||||
goto nextopcode;
|
||||
case O_OUTd:
|
||||
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
|
||||
IO_WriteD(inst.op1.d,reg_eax);
|
||||
goto nextopcode;
|
||||
case O_CBACK:
|
||||
LEAVECORE;
|
||||
FillFlags();SaveIP();
|
||||
return inst.op1.d;
|
||||
case O_GRP6w:
|
||||
case O_GRP6d:
|
||||
|
|
|
@ -110,8 +110,9 @@ static OpCode OpCodeTable[1024]={
|
|||
/* 0x98 - 0x9f */
|
||||
{D_CBW ,0 ,0 ,0 },{D_CWD ,0 ,0 ,0 },
|
||||
{L_Ifw ,O_CALLFw ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
|
||||
{L_FLG ,0 ,S_PUSHw,0 },{L_PFLGw ,0 ,0 ,0 },
|
||||
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
|
||||
{D_PUSHF ,0 ,0 ,0 },{D_POPF ,0 ,0 ,0 },
|
||||
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
|
||||
|
||||
|
||||
/* 0xa0 - 0xa7 */
|
||||
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_AXOP ,0 ,0 },
|
||||
|
@ -466,8 +467,8 @@ static OpCode OpCodeTable[1024]={
|
|||
/* 0x298 - 0x29f */
|
||||
{D_CWDE ,0 ,0 ,0 },{D_CDQ ,0 ,0 ,0 },
|
||||
{L_Ifd ,O_CALLFd ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
|
||||
{L_FLG ,0 ,S_PUSHd,0 },{L_PFLGd ,0 ,0 ,0 },
|
||||
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
|
||||
{D_PUSHF ,0 ,0 ,true },{D_POPF ,0 ,0 ,true },
|
||||
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
|
||||
|
||||
/* 0x2a0 - 0x2a7 */
|
||||
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_EAXOP ,0 ,0 },
|
||||
|
|
|
@ -56,29 +56,14 @@ switch (inst.code.save) {
|
|||
reg_32(inst.code.extra)=inst.op1.d;
|
||||
break;
|
||||
case S_SEGm:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) RunException();
|
||||
break;
|
||||
case S_SEGGw:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
|
||||
reg_16(inst.rm_index)=inst.op1.w;
|
||||
break;
|
||||
case S_SEGGd:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
|
||||
reg_32(inst.rm_index)=inst.op1.d;
|
||||
break;
|
||||
case S_PUSHw:
|
||||
|
@ -94,25 +79,19 @@ switch (inst.code.save) {
|
|||
SaveIP();
|
||||
reg_eip+=inst.op1.d;
|
||||
reg_eip&=0xffff;
|
||||
LoadIP();
|
||||
break;
|
||||
continue;
|
||||
case S_C_AIPd:
|
||||
if (!inst.cond) goto nextopcode;
|
||||
case S_AIPd:
|
||||
SaveIP();
|
||||
reg_eip+=inst.op1.d;
|
||||
LoadIP();
|
||||
break;
|
||||
continue;
|
||||
case S_IPIw:
|
||||
reg_esp+=Fetchw();
|
||||
case S_IP:
|
||||
SaveIP();
|
||||
reg_eip=inst.op1.d;
|
||||
LoadIP();
|
||||
break;
|
||||
case S_FLGb:
|
||||
SETFLAGSb(inst.op1.b);
|
||||
break;
|
||||
continue;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
count_left=count-CPU_Cycles;
|
||||
count=CPU_Cycles;
|
||||
CPU_Cycles=0;
|
||||
IPPoint=inst.opcode_start; //Reset IP to start of instruction
|
||||
LoadIP();
|
||||
} else {
|
||||
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
|
||||
count_left=0;
|
||||
|
|
|
@ -13,11 +13,9 @@ enum {
|
|||
L_REGbIb,L_REGwIw,L_REGdId,
|
||||
L_POPw,L_POPd,
|
||||
L_POPfw,L_POPfd,
|
||||
L_PFLGw,L_PFLGd,
|
||||
L_SEG,
|
||||
|
||||
L_FLG,L_INTO,
|
||||
|
||||
L_INTO,
|
||||
|
||||
L_VAL,
|
||||
L_PRESEG,
|
||||
|
@ -43,6 +41,8 @@ enum {
|
|||
|
||||
D_RETFw,D_RETFd,
|
||||
D_RETFwIw,D_RETFdIw,
|
||||
D_POPF,D_PUSHF,
|
||||
D_SAHF,D_LAHF,
|
||||
D_CPUID,
|
||||
D_HLT,D_CLTS,
|
||||
L_ERROR,
|
||||
|
@ -115,7 +115,6 @@ enum {
|
|||
S_AIPw,S_C_AIPw,
|
||||
S_AIPd,S_C_AIPd,
|
||||
|
||||
S_FLGb,
|
||||
S_IP,S_IPIw,
|
||||
};
|
||||
|
||||
|
@ -157,7 +156,6 @@ struct OpCode {
|
|||
|
||||
struct FullData {
|
||||
Bitu entry;
|
||||
EAPoint opcode_start;
|
||||
Bitu rm;
|
||||
EAPoint rm_eaa;
|
||||
Bitu rm_off;
|
||||
|
@ -165,6 +163,7 @@ struct FullData {
|
|||
Bitu rm_index;
|
||||
Bitu rm_mod;
|
||||
OpCode code;
|
||||
EAPoint cseip;
|
||||
union {
|
||||
Bit8u b;Bit8s bs;
|
||||
Bit16u w;Bit16s ws;
|
||||
|
@ -177,13 +176,11 @@ struct FullData {
|
|||
Bitu cond;
|
||||
bool repz;
|
||||
Bitu prefix;
|
||||
Bitu start_prefix;
|
||||
Bitu start_entry;
|
||||
};
|
||||
|
||||
|
||||
#define PREFIX_NONE 0x0
|
||||
#define PREFIX_SEG 0x1
|
||||
#define PREFIX_ADDR 0x2
|
||||
#define PREFIX_ADDR 0x1
|
||||
#define PREFIX_SEG 0x2
|
||||
#define PREFIX_REP 0x4
|
||||
|
||||
|
|
|
@ -81,9 +81,9 @@ extern Bitu cycle_count;
|
|||
#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_ADDR 0x1
|
||||
#define PREFIX_SEG 0x2
|
||||
#define PREFIX_SEG_ADDR (PREFIX_ADDR|PREFIX_SEG)
|
||||
#define PREFIX_REP 0x4
|
||||
|
||||
#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG)
|
||||
|
@ -95,9 +95,9 @@ extern Bitu cycle_count;
|
|||
core.seg_prefix_base=SegBase(_SEG); \
|
||||
goto restart_prefix;
|
||||
|
||||
#define DO_PREFIX_ADDR() \
|
||||
core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
|
||||
(core.prefix_default ^ PREFIX_ADDR) & PREFIX_ADDR; \
|
||||
#define DO_PREFIX_ADDR() \
|
||||
core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
|
||||
(cpu.code.big ^ PREFIX_ADDR); \
|
||||
goto restart_prefix;
|
||||
|
||||
#define DO_PREFIX_REP(_ZERO) \
|
||||
|
@ -107,15 +107,14 @@ extern Bitu cycle_count;
|
|||
|
||||
typedef PhysPt (*GetEATable[256])(void);
|
||||
|
||||
static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
|
||||
|
||||
static struct {
|
||||
Bitu opcode_index;
|
||||
Bitu prefixes;
|
||||
Bitu index_default;
|
||||
Bitu prefix_default;
|
||||
PhysPt op_start;
|
||||
PhysPt ip_lookup;
|
||||
PhysPt cseip;
|
||||
PhysPt seg_prefix_base;
|
||||
bool rep_zero;
|
||||
Bitu prefixes;
|
||||
GetEATable * ea_table;
|
||||
struct {
|
||||
bool skip;
|
||||
|
@ -127,8 +126,8 @@ static struct {
|
|||
#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,
|
||||
&GetEA_NONE,&GetEA_ADDR,&GetEA_SEG,&GetEA_SEG_ADDR,
|
||||
&GetEA_NONE,&GetEA_ADDR,&GetEA_SEG,&GetEA_SEG_ADDR,
|
||||
};
|
||||
|
||||
#define CASE_W(_WHICH) \
|
||||
|
@ -154,29 +153,18 @@ static GetEATable * EAPrefixTable[8] = {
|
|||
#define EALookupTable (*(core.ea_table))
|
||||
|
||||
Bits CPU_Core_Normal_Run(void) {
|
||||
decode_start:
|
||||
if (cpu.code.big) {
|
||||
core.index_default=0x200;
|
||||
core.prefix_default=PREFIX_ADDR;
|
||||
} else {
|
||||
core.index_default=0;
|
||||
core.prefix_default=0;
|
||||
}
|
||||
LOADIP;
|
||||
lflags.type=t_UNKNOWN;
|
||||
while (CPU_Cycles-->0) {
|
||||
core.op_start=core.ip_lookup;
|
||||
core.opcode_index=core.index_default;
|
||||
core.prefixes=core.prefix_default;
|
||||
LOADIP;
|
||||
core.opcode_index=cpu.code.big*0x200;
|
||||
core.prefixes=cpu.code.big;
|
||||
#if C_DEBUG
|
||||
cycle_count++;
|
||||
#if C_HEAVY_DEBUG
|
||||
SAVEIP;
|
||||
if (DEBUG_HeavyIsBreakpoint()) {
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
return debugCallback;
|
||||
};
|
||||
#endif
|
||||
cycle_count++;
|
||||
#endif
|
||||
restart_prefix:
|
||||
core.ea_table=EAPrefixTable[core.prefixes];
|
||||
|
@ -189,27 +177,29 @@ restart_opcode:
|
|||
#include "core_normal/prefix_66_0f.h"
|
||||
default:
|
||||
illegal_opcode:
|
||||
LEAVECORE;
|
||||
reg_eip-=core.ip_lookup-core.op_start;
|
||||
#if C_DEBUG
|
||||
{
|
||||
Bitu len=core.ip_lookup-core.op_start;
|
||||
Bitu len=(GETIP-reg_eip);
|
||||
LOADIP;
|
||||
if (len>16) len=16;
|
||||
char tempcode[16*2+1];char * writecode=tempcode;
|
||||
for (;len>0;len--) {
|
||||
sprintf(writecode,"%X",mem_readb(core.op_start++));
|
||||
sprintf(writecode,"%X",mem_readb(core.cseip++));
|
||||
writecode+=2;
|
||||
}
|
||||
LOG(LOG_CPU,LOG_ERROR)("Illegal/Unhandled opcode %s",tempcode);
|
||||
}
|
||||
#endif
|
||||
CPU_Exception(6,0);
|
||||
goto decode_start;
|
||||
|
||||
continue;
|
||||
}
|
||||
SAVEIP;
|
||||
}
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
decode_end:
|
||||
LEAVECORE;
|
||||
SAVEIP;
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
|
@ -220,7 +210,7 @@ Bits CPU_Core_Normal_Trap_Run(void) {
|
|||
core.trap.skip=false;
|
||||
|
||||
Bits ret=CPU_Core_Normal_Run();
|
||||
if (!core.trap.skip) CPU_SW_Interrupt(1,0);
|
||||
if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip);
|
||||
CPU_Cycles = oldCycles-1;
|
||||
cpudecoder = &CPU_Core_Normal_Run;
|
||||
|
||||
|
|
|
@ -141,17 +141,3 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \
|
||||
if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \
|
||||
LEAVECORE; \
|
||||
reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \
|
||||
CPU_StartException();goto decode_start; \
|
||||
}
|
||||
|
||||
#define LOADSEG(_SEG_,_SEG_VAL_) \
|
||||
if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \
|
||||
LEAVECORE; \
|
||||
reg_eip-=(core.ip_lookup-core.op_start); \
|
||||
CPU_StartException();goto decode_start; \
|
||||
} \
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
|
||||
goto illegal_opcode;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -77,7 +77,7 @@
|
|||
break;
|
||||
case 0x06: /* LMSW */
|
||||
limit=LoadMw(eaa);
|
||||
if (!CPU_LMSW(limit)) goto decode_end;
|
||||
if (CPU_LMSW(limit)) RUNEXCEPTION();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -88,11 +88,10 @@
|
|||
*earw=limit;
|
||||
break;
|
||||
case 0x06: /* LMSW */
|
||||
if (!CPU_LMSW(*earw)) goto decode_end;
|
||||
if (CPU_LMSW(*earw)) RUNEXCEPTION();
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
|
||||
break;
|
||||
goto illegal_opcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,11 +153,8 @@
|
|||
Bitu which=(rm >> 3) & 7;
|
||||
if (rm >= 0xc0 ) {
|
||||
GetEArd;
|
||||
CPU_SET_CRX(which,*eard);
|
||||
} else {
|
||||
GetEAa;
|
||||
LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which);
|
||||
}
|
||||
if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION();
|
||||
} else goto illegal_opcode;
|
||||
}
|
||||
break;
|
||||
CASE_0F_B(0x23) /* MOV DRx,Rd */
|
||||
|
@ -241,7 +237,7 @@
|
|||
CASE_0F_W(0xa0) /* PUSH FS */
|
||||
Push_16(SegValue(fs));break;
|
||||
CASE_0F_W(0xa1) /* POP FS */
|
||||
POPSEG(fs,Pop_16(),2);
|
||||
if (CPU_PopSeg(fs,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_B(0xa2) /* CPUID */
|
||||
CPU_CPUID();break;
|
||||
|
@ -268,7 +264,8 @@
|
|||
CASE_0F_W(0xa8) /* PUSH GS */
|
||||
Push_16(SegValue(gs));break;
|
||||
CASE_0F_W(0xa9) /* POP GS */
|
||||
POPSEG(gs,Pop_16(),2);break;
|
||||
if (CPU_PopSeg(gs,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_W(0xab) /* BTS Ew,Gw */
|
||||
{
|
||||
FillFlags();GetRMrw;
|
||||
|
@ -297,7 +294,7 @@
|
|||
CASE_0F_W(0xb2) /* LSS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(ss,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -320,14 +317,14 @@
|
|||
CASE_0F_W(0xb4) /* LFS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(fs,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_0F_W(0xb5) /* LGS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(gs,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
CASE_D(0x06) /* PUSH ES */
|
||||
Push_32(SegValue(es));break;
|
||||
CASE_D(0x07) /* POP ES */
|
||||
POPSEG(es,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(es,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x09) /* OR Ed,Gd */
|
||||
RMEdGd(ORD);break;
|
||||
CASE_D(0x0b) /* OR Gd,Ed */
|
||||
|
@ -43,7 +44,7 @@
|
|||
CASE_D(0x16) /* PUSH SS */
|
||||
Push_32(SegValue(ss));break;
|
||||
CASE_D(0x17) /* POP SS */
|
||||
POPSEG(ss,Pop_32(),4);
|
||||
if (CPU_PopSeg(ss,true)) RUNEXCEPTION();
|
||||
CPU_Cycles++;
|
||||
break;
|
||||
CASE_D(0x19) /* SBB Ed,Gd */
|
||||
|
@ -55,7 +56,8 @@
|
|||
CASE_D(0x1e) /* PUSH DS */
|
||||
Push_32(SegValue(ds));break;
|
||||
CASE_D(0x1f) /* POP DS */
|
||||
POPSEG(ds,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(ds,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x21) /* AND Ed,Gd */
|
||||
RMEdGd(ANDD);break;
|
||||
CASE_D(0x23) /* AND Gd,Ed */
|
||||
|
@ -191,6 +193,12 @@
|
|||
CASE_D(0x6b) /* IMUL Gd,Ed,Ib */
|
||||
RMGdEdOp3(DIMULD,Fetchbs());
|
||||
break;
|
||||
CASE_D(0x6d) /* INSD */
|
||||
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
|
||||
DoString(R_INSD);break;
|
||||
CASE_D(0x6f) /* OUTSD */
|
||||
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
|
||||
DoString(R_OUTSD);break;
|
||||
CASE_D(0x70) /* JO */
|
||||
JumpCond32_b(TFLG_O);break;
|
||||
CASE_D(0x71) /* JNO */
|
||||
|
@ -379,21 +387,17 @@
|
|||
CASE_D(0x9a) /* CALL FAR Ad */
|
||||
{
|
||||
Bit32u newip=Fetchd();Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0x9c) /* PUSHFD */
|
||||
FillFlags();
|
||||
Push_32(reg_flags);
|
||||
if (CPU_PUSHF(true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x9d) /* POPFD */
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGSd(Pop_32())
|
||||
if (CPU_POPF(true)) RUNEXCEPTION();
|
||||
lflags.type=t_UNKNOWN;
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
|
@ -403,7 +407,6 @@
|
|||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
|
||||
#endif
|
||||
|
||||
break;
|
||||
CASE_D(0xa1) /* MOV EAX,Od */
|
||||
{
|
||||
|
@ -448,25 +451,23 @@
|
|||
CASE_D(0xc1) /* GRP2 Ed,Ib */
|
||||
GRP2D(Fetchb());break;
|
||||
CASE_D(0xc2) /* RETN Iw */
|
||||
{
|
||||
Bit16u addsp=Fetchw();
|
||||
SETIP(Pop_32());reg_esp+=addsp;
|
||||
break;
|
||||
}
|
||||
reg_eip=Pop_32();
|
||||
reg_esp+=Fetchw();
|
||||
continue;
|
||||
CASE_D(0xc3) /* RETN */
|
||||
SETIP(Pop_32());
|
||||
break;
|
||||
reg_eip=Pop_32();
|
||||
continue;
|
||||
CASE_D(0xc4) /* LES */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(es,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xc5) /* LDS */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(ds,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -479,36 +480,11 @@
|
|||
}
|
||||
CASE_D(0xc8) /* ENTER Iw,Ib */
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-4;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=4;reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=4;reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_ebp=frame_ptr;
|
||||
break;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(true,bytes,level);
|
||||
}
|
||||
break;
|
||||
CASE_D(0xc9) /* LEAVE */
|
||||
reg_esp&=~cpu.stack.mask;
|
||||
reg_esp|=(reg_ebp&cpu.stack.mask);
|
||||
|
@ -517,20 +493,20 @@
|
|||
CASE_D(0xca) /* RETF Iw */
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(true,words,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(true,words,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xcb) /* RETF */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_RET(true,0,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(true,0,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xcf) /* IRET */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_IRET(true,core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_IRET(true,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
|
@ -540,35 +516,79 @@
|
|||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xd1) /* GRP2 Ed,1 */
|
||||
GRP2D(1);break;
|
||||
CASE_D(0xd3) /* GRP2 Ed,CL */
|
||||
GRP2D(reg_cl);break;
|
||||
CASE_D(0xe0) /* LOOPNZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx && !get_ZF());
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx && !get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe1) /* LOOPZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx && get_ZF());
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx && get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe2) /* LOOP */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx);
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx);
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe3) /* JCXZ */
|
||||
JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
|
||||
break;
|
||||
CASE_D(0xe5) /* IN EAX,Ib */
|
||||
reg_eax=IO_ReadD(Fetchb());
|
||||
break;
|
||||
CASE_D(0xe7) /* OUT Ib,EAX */
|
||||
IO_WriteD(Fetchb(),reg_eax);
|
||||
break;
|
||||
CASE_D(0xe8) /* CALL Jd */
|
||||
{
|
||||
Bit32s newip=Fetchds();
|
||||
Push_32((Bit32u)GETIP);
|
||||
ADDIPd(newip);
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
|
||||
reg_eax=IO_ReadD(port);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xe7) /* OUT Ib,EAX */
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
|
||||
IO_WriteD(port,reg_eax);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xe8) /* CALL Jd */
|
||||
{
|
||||
Bit32s addip=Fetchds();
|
||||
SAVEIP;
|
||||
Push_32(reg_eip);
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xe9) /* JMP Jd */
|
||||
ADDIPd(Fetchds());
|
||||
break;
|
||||
{
|
||||
Bit32s addip=Fetchds();
|
||||
SAVEIP;
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xea) /* JMP Ad */
|
||||
{
|
||||
Bit32u newip=Fetchd();
|
||||
Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xeb) /* JMP Jb */
|
||||
{
|
||||
Bit32s addip=Fetchbs();
|
||||
SAVEIP;
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xed) /* IN EAX,DX */
|
||||
reg_eax=IO_ReadD(reg_dx);
|
||||
|
@ -631,31 +651,31 @@
|
|||
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;
|
||||
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
|
||||
else {GetEAa;reg_eip=LoadMd(eaa);}
|
||||
Push_32(GETIP);
|
||||
continue;
|
||||
case 0x03: /* CALL FAR Ed */
|
||||
{
|
||||
GetEAa;
|
||||
Bit32u newip=LoadMd(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+4);
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x04: /* JMP NEAR Ed */
|
||||
if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);}
|
||||
else {GetEAa;SETIP(LoadMd(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
|
||||
else {GetEAa;reg_eip=LoadMd(eaa);}
|
||||
continue;
|
||||
case 0x05: /* JMP FAR Ed */
|
||||
{
|
||||
GetEAa;
|
||||
Bit32u newip=LoadMd(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+4);
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* Push Ed */
|
||||
|
|
|
@ -159,7 +159,8 @@
|
|||
CASE_0F_D(0xa0) /* PUSH FS */
|
||||
Push_32(SegValue(fs));break;
|
||||
CASE_0F_D(0xa1) /* POP FS */
|
||||
POPSEG(fs,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(fs,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_D(0xa3) /* BT Ed,Gd */
|
||||
{
|
||||
FillFlags();GetRMrd;
|
||||
|
@ -183,7 +184,8 @@
|
|||
CASE_0F_D(0xa8) /* PUSH GS */
|
||||
Push_32(SegValue(gs));break;
|
||||
CASE_0F_D(0xa9) /* POP GS */
|
||||
POPSEG(gs,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(gs,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_D(0xab) /* BTS Ed,Gd */
|
||||
{
|
||||
FillFlags();GetRMrd;
|
||||
|
@ -215,7 +217,7 @@
|
|||
CASE_0F_D(0xb2) /* LSS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(ss,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -238,14 +240,14 @@
|
|||
CASE_0F_D(0xb4) /* LFS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(fs,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_0F_D(0xb5) /* LGS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(gs,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
CASE_W(0x06) /* PUSH ES */
|
||||
Push_16(SegValue(es));break;
|
||||
CASE_W(0x07) /* POP ES */
|
||||
POPSEG(es,Pop_16(),2);break;
|
||||
if (CPU_PopSeg(es,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0x08) /* OR Eb,Gb */
|
||||
RMEbGb(ORB);break;
|
||||
CASE_W(0x09) /* OR Ew,Gw */
|
||||
|
@ -65,7 +66,7 @@
|
|||
CASE_W(0x16) /* PUSH SS */
|
||||
Push_16(SegValue(ss));break;
|
||||
CASE_W(0x17) /* POP SS */
|
||||
POPSEG(ss,Pop_16(),2);
|
||||
if (CPU_PopSeg(ss,false)) RUNEXCEPTION();
|
||||
CPU_Cycles++; //Always do another instruction
|
||||
break;
|
||||
CASE_B(0x18) /* SBB Eb,Gb */
|
||||
|
@ -83,7 +84,7 @@
|
|||
CASE_W(0x1e) /* PUSH DS */
|
||||
Push_16(SegValue(ds));break;
|
||||
CASE_W(0x1f) /* POP DS */
|
||||
POPSEG(ds,Pop_16(),2);
|
||||
if (CPU_PopSeg(ds,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0x20) /* AND Eb,Gb */
|
||||
RMEbGb(ANDB);break;
|
||||
|
@ -256,7 +257,7 @@
|
|||
CASE_B(0x65) /* SEG GS: */
|
||||
DO_PREFIX_SEG(gs);break;
|
||||
CASE_B(0x66) /* Operand Size Prefix */
|
||||
core.opcode_index=core.index_default^OPCODE_SIZE;
|
||||
core.opcode_index=(cpu.code.big^0x1)*0x200;
|
||||
goto restart_opcode;
|
||||
CASE_B(0x67) /* Address Size Prefix */
|
||||
DO_PREFIX_ADDR();
|
||||
|
@ -272,12 +273,16 @@
|
|||
RMGwEwOp3(DIMULW,Fetchbs());
|
||||
break;
|
||||
CASE_B(0x6c) /* INSB */
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
DoString(R_INSB);break;
|
||||
CASE_W(0x6d) /* INSW */
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
DoString(R_INSW);break;
|
||||
CASE_B(0x6e) /* OUTSB */
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
DoString(R_OUTSB);break;
|
||||
CASE_W(0x6f) /* OUTSW */
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
DoString(R_OUTSW);break;
|
||||
CASE_W(0x70) /* JO */
|
||||
JumpCond16_b(TFLG_O);break;
|
||||
|
@ -498,13 +503,10 @@
|
|||
case 0x03: /* MOV DS,Ew */
|
||||
case 0x05: /* MOV GS,Ew */
|
||||
case 0x04: /* MOV FS,Ew */
|
||||
LOADSEG((SegNames)which,val);
|
||||
break;
|
||||
case 0x01: /* MOV CS,Ew Illegal*/
|
||||
E_Exit("CPU:Illegal MOV CS Call");
|
||||
if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION();
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:8E:Illegal RM Byte");
|
||||
goto illegal_opcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -546,24 +548,20 @@
|
|||
break;
|
||||
CASE_W(0x9a) /* CALL Ap */
|
||||
{
|
||||
FillFlags();
|
||||
Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
CPU_CALL(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_B(0x9b) /* WAIT */
|
||||
break; /* No waiting here */
|
||||
CASE_W(0x9c) /* PUSHF */
|
||||
FillFlags();
|
||||
Push_16(reg_flags);
|
||||
if (CPU_PUSHF(false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_W(0x9d) /* POPF */
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGSw(Pop_16());
|
||||
if (CPU_POPF(false)) RUNEXCEPTION();
|
||||
lflags.type=t_UNKNOWN;
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
|
@ -666,25 +664,23 @@
|
|||
CASE_W(0xc1) /* GRP2 Ew,Ib */
|
||||
GRP2W(Fetchb());break;
|
||||
CASE_W(0xc2) /* RETN Iw */
|
||||
{
|
||||
Bit16u addsp=Fetchw();
|
||||
SETIP(Pop_16());reg_esp+=addsp;
|
||||
break;
|
||||
}
|
||||
reg_eip=Pop_16();
|
||||
reg_esp+=Fetchw();
|
||||
continue;
|
||||
CASE_W(0xc3) /* RETN */
|
||||
SETIP(Pop_16());
|
||||
break;
|
||||
reg_eip=Pop_16();
|
||||
continue;
|
||||
CASE_W(0xc4) /* LES */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(es,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xc5) /* LDS */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(ds,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -704,36 +700,11 @@
|
|||
}
|
||||
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<level;i++) {
|
||||
reg_ebp-=2;reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=2;reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_bp=frame_ptr;
|
||||
break;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(false,bytes,level);
|
||||
}
|
||||
break;
|
||||
CASE_W(0xc9) /* LEAVE */
|
||||
reg_esp&=~cpu.stack.mask;
|
||||
reg_esp|=(reg_ebp&cpu.stack.mask);
|
||||
|
@ -741,58 +712,55 @@
|
|||
break;
|
||||
CASE_W(0xca) /* RETF Iw */
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(false,words,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
Bitu words=Fetchw();
|
||||
FillFlags();
|
||||
CPU_RET(false,words,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xcb) /* RETF */
|
||||
LEAVECORE;
|
||||
CPU_RET(false,0,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(false,0,GETIP);
|
||||
continue;
|
||||
CASE_B(0xcc) /* INT3 */
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (DEBUG_Breakpoint()) {
|
||||
if (DEBUG_Breakpoint())
|
||||
return debugCallback;
|
||||
}
|
||||
#endif
|
||||
CPU_SW_Interrupt(3,(core.ip_lookup-core.op_start));
|
||||
CPU_SW_Interrupt(3,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
CASE_B(0xcd) /* INT Ib */
|
||||
{
|
||||
Bit8u num=Fetchb();
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (DEBUG_IntBreakpoint(num)) {
|
||||
return debugCallback;
|
||||
}
|
||||
#endif
|
||||
CPU_SW_Interrupt(num,core.ip_lookup-core.op_start);
|
||||
CPU_SW_Interrupt(num,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_B(0xce) /* INTO */
|
||||
if (get_OF()) {
|
||||
LEAVECORE;
|
||||
CPU_SW_Interrupt(4,core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_SW_Interrupt(4,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_W(0xcf) /* IRET */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_IRET(false,core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_IRET(false,GETIP);
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
|
||||
#endif
|
||||
|
@ -802,7 +770,7 @@
|
|||
return CBRET_NONE;
|
||||
}
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
CASE_B(0xd0) /* GRP2 Eb,1 */
|
||||
GRP2B(1);break;
|
||||
|
@ -867,84 +835,104 @@
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
CASE_B(0xe0) /* LOOPNZ */
|
||||
CASE_W(0xe0) /* LOOPNZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx && !get_ZF());
|
||||
} else {
|
||||
if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx && !get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe1) /* LOOPZ */
|
||||
CASE_W(0xe1) /* LOOPZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx) && get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx && get_ZF());
|
||||
} else {
|
||||
if ((--reg_cx) && get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx && get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe2) /* LOOP */
|
||||
CASE_W(0xe2) /* LOOP */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx)) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx);
|
||||
} else {
|
||||
if ((--reg_cx)) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx);
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe3) /* JCXZ */
|
||||
{
|
||||
Bitu test;
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
test=reg_ecx;
|
||||
} else test=reg_cx;
|
||||
if (!test) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
CASE_W(0xe3) /* JCXZ */
|
||||
JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
|
||||
break;
|
||||
CASE_B(0xe4) /* IN AL,Ib */
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadB(port);
|
||||
break;
|
||||
}
|
||||
CASE_B(0xe4) /* IN AL,Ib */
|
||||
reg_al=IO_ReadB(Fetchb());
|
||||
break;
|
||||
CASE_W(0xe5) /* IN AX,Ib */
|
||||
reg_ax=IO_ReadW(Fetchb());
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadW(port);
|
||||
break;
|
||||
}
|
||||
CASE_B(0xe6) /* OUT Ib,AL */
|
||||
IO_WriteB(Fetchb(),reg_al);
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
|
||||
IO_WriteB(port,reg_al);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xe7) /* OUT Ib,AX */
|
||||
IO_WriteW(Fetchb(),reg_ax);
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
|
||||
IO_WriteW(port,reg_ax);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xe8) /* CALL Jw */
|
||||
{
|
||||
Bit16s newip=Fetchws();
|
||||
Push_16((Bit16u)GETIP);
|
||||
ADDIPw(newip);
|
||||
break;
|
||||
Bit16u addip=Fetchws();
|
||||
SAVEIP;
|
||||
Push_16(reg_eip);
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xe9) /* JMP Jw */
|
||||
ADDIPw(Fetchws());
|
||||
break;
|
||||
{
|
||||
Bit16u addip=Fetchws();
|
||||
SAVEIP;
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xea) /* JMP Ap */
|
||||
{
|
||||
Bit16u newip=Fetchw();
|
||||
Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xeb) /* JMP Jb */
|
||||
{
|
||||
Bit16s addip=Fetchbs();
|
||||
SAVEIP;
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_B(0xeb) /* JMP Jb */
|
||||
ADDIPFAST(Fetchbs());break;
|
||||
CASE_B(0xec) /* IN AL,DX */
|
||||
reg_al=IO_Read(reg_dx);break;
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadB(reg_dx);
|
||||
break;
|
||||
CASE_W(0xed) /* IN AX,DX */
|
||||
reg_al=IO_Read(reg_dx);reg_ah=IO_Read(reg_dx+1);
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
reg_ax=IO_ReadW(reg_dx);
|
||||
break;
|
||||
CASE_B(0xee) /* OUT DX,AL */
|
||||
IO_WriteB(reg_dx,reg_al);break;
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
IO_WriteB(reg_dx,reg_al);
|
||||
break;
|
||||
CASE_W(0xef) /* OUT DX,AX */
|
||||
IO_WriteW(reg_dx,reg_ax);break;
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
IO_WriteW(reg_dx,reg_ax);
|
||||
break;
|
||||
CASE_B(0xf0) /* LOCK */
|
||||
LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
|
||||
break;
|
||||
|
@ -955,8 +943,8 @@
|
|||
DO_PREFIX_REP(true);
|
||||
break;
|
||||
CASE_B(0xf4) /* HLT */
|
||||
LEAVECORE;
|
||||
CPU_HLT(core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_HLT(GETIP);
|
||||
return CBRET_NONE; //Needs to return for hlt cpu core
|
||||
CASE_B(0xf5) /* CMC */
|
||||
FillFlags();
|
||||
|
@ -1059,14 +1047,10 @@
|
|||
SETFLAGBIT(CF,true);
|
||||
break;
|
||||
CASE_B(0xfa) /* CLI */
|
||||
LEAVECORE;
|
||||
if (CPU_CLI(core.ip_lookup-core.op_start))
|
||||
goto decode_start;
|
||||
if (CPU_CLI()) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0xfb) /* STI */
|
||||
LEAVECORE;
|
||||
if (CPU_STI(core.ip_lookup-core.op_start))
|
||||
goto decode_start;
|
||||
if (CPU_STI()) RUNEXCEPTION();
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
|
||||
#endif
|
||||
|
@ -1092,7 +1076,7 @@
|
|||
case 0x07: /* CallBack */
|
||||
{
|
||||
Bitu cb=Fetchw();
|
||||
LEAVECORE;
|
||||
FillFlags();SAVEIP;
|
||||
return cb;
|
||||
}
|
||||
default:
|
||||
|
@ -1112,31 +1096,32 @@
|
|||
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;
|
||||
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
|
||||
else {GetEAa;reg_eip=LoadMw(eaa);}
|
||||
Push_16(GETIP);
|
||||
continue;
|
||||
case 0x03: /* CALL Ep */
|
||||
{
|
||||
GetEAa;
|
||||
Bit16u newip=LoadMw(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+2);
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x04: /* JMP Ev */
|
||||
if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);}
|
||||
else {GetEAa;SETIP(LoadMw(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
|
||||
else {GetEAa;reg_eip=LoadMw(eaa);}
|
||||
continue;
|
||||
case 0x05: /* JMP Ep */
|
||||
{
|
||||
GetEAa;
|
||||
Bit16u newip=LoadMw(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+2);
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* PUSH Ev */
|
||||
|
|
|
@ -20,18 +20,11 @@ static void DoString(STRING_OP type) {
|
|||
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)) {
|
||||
add_mask=AddrMaskTable[core.prefixes& PREFIX_ADDR];
|
||||
si_index=reg_esi & add_mask;
|
||||
di_index=reg_edi & add_mask;
|
||||
count=reg_ecx & add_mask;
|
||||
if (!TEST_PREFIX_REP) {
|
||||
count=1;
|
||||
} else {
|
||||
CPU_Cycles++;
|
||||
|
@ -40,7 +33,7 @@ static void DoString(STRING_OP type) {
|
|||
count_left=count-CPU_Cycles;
|
||||
count=CPU_Cycles;
|
||||
CPU_Cycles=0;
|
||||
core.ip_lookup=core.op_start; //Reset IP to start of instruction
|
||||
LOADIP; //RESET IP to the start
|
||||
} else {
|
||||
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
|
||||
count_left=0;
|
||||
|
|
|
@ -16,57 +16,36 @@
|
|||
* 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 GETIP (core.cseip-SegBase(cs))
|
||||
#define SAVEIP reg_eip=GETIP;
|
||||
#define LOADIP core.cseip=(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;
|
||||
SAVEIP;
|
||||
reg_eip=(reg_eip+blah);
|
||||
LOADIP;
|
||||
#define RUNEXCEPTION() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define EXCEPTION(blah) \
|
||||
{ \
|
||||
Bit8u new_num=blah; \
|
||||
core.ip_lookup=core.op_start; \
|
||||
LEAVECORE; \
|
||||
CPU_Exception(new_num); \
|
||||
goto decode_start; \
|
||||
CPU_Exception(blah); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
static INLINE Bit8u Fetchb() {
|
||||
Bit8u temp=LoadMb(core.ip_lookup);
|
||||
core.ip_lookup+=1;
|
||||
Bit8u temp=LoadMb(core.cseip);
|
||||
core.cseip+=1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static INLINE Bit16u Fetchw() {
|
||||
Bit16u temp=LoadMw(core.ip_lookup);
|
||||
core.ip_lookup+=2;
|
||||
Bit16u temp=LoadMw(core.cseip);
|
||||
core.cseip+=2;
|
||||
return temp;
|
||||
}
|
||||
static INLINE Bit32u Fetchd() {
|
||||
Bit32u temp=LoadMd(core.ip_lookup);
|
||||
core.ip_lookup+=4;
|
||||
Bit32u temp=LoadMd(core.cseip);
|
||||
core.cseip+=4;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
@ -81,68 +60,40 @@ static INLINE Bit32s Fetchds() {
|
|||
return Fetchd();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define Push_16 CPU_Push16
|
||||
#define Push_32 CPU_Push32
|
||||
#define Pop_16 CPU_Pop16
|
||||
#define Pop_32 CPU_Pop32
|
||||
|
||||
#endif
|
||||
|
||||
//TODO Could probably make all byte operands fast?
|
||||
#define JumpCond16_b(blah) \
|
||||
if (blah) { \
|
||||
ADDIPw(Fetchbs()); \
|
||||
} else { \
|
||||
ADDIPFAST(1); \
|
||||
}
|
||||
#define JumpCond16_b(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_ip+=Fetchbs(); \
|
||||
reg_ip+=1; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_b(blah) \
|
||||
if (blah) { \
|
||||
ADDIPd(Fetchbs()); \
|
||||
} else { \
|
||||
ADDIPFAST(1); \
|
||||
}
|
||||
#define JumpCond16_w(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_ip+=Fetchws(); \
|
||||
reg_ip+=2; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond16_w(blah) \
|
||||
if (blah) { \
|
||||
ADDIPw(Fetchws()); \
|
||||
} else { \
|
||||
ADDIPFAST(2); \
|
||||
}
|
||||
#define JumpCond32_b(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_eip+=Fetchbs(); \
|
||||
reg_eip+=1; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_d(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_eip+=Fetchds(); \
|
||||
reg_eip+=4; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_d(blah) \
|
||||
if (blah) { \
|
||||
ADDIPd(Fetchds()); \
|
||||
} else { \
|
||||
ADDIPFAST(4); \
|
||||
}
|
||||
|
||||
#define SETcc(cc) \
|
||||
{ \
|
||||
|
|
181
src/cpu/cpu.cpp
181
src/cpu/cpu.cpp
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cpu.cpp,v 1.55 2004-03-31 17:24:30 harekiet Exp $ */
|
||||
/* $Id: cpu.cpp,v 1.56 2004-04-22 22:40:45 harekiet Exp $ */
|
||||
|
||||
#include <assert.h>
|
||||
#include "dosbox.h"
|
||||
|
@ -46,10 +46,6 @@ Bits CPU_CycleUp = 0;
|
|||
Bits CPU_CycleDown = 0;
|
||||
CPU_Decoder * cpudecoder;
|
||||
|
||||
static struct {
|
||||
Bitu which,errorcode;
|
||||
} exception;
|
||||
|
||||
void CPU_Core_Full_Init(void);
|
||||
void CPU_Core_Normal_Init(void);
|
||||
void CPU_Core_Dyn_X86_Init(void);
|
||||
|
@ -91,28 +87,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) {
|
|||
cpu.direction=1-((reg_flags & FLAG_DF) >> 9);
|
||||
}
|
||||
|
||||
bool CPU_CLI(Bitu opLen) {
|
||||
static bool CPU_PrepareException(Bitu which,Bitu error) {
|
||||
cpu.exception.which=which;
|
||||
cpu.exception.error=error;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPU_CLI(void) {
|
||||
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return true;
|
||||
return CPU_PrepareException(13,0);
|
||||
} else {
|
||||
SETFLAGBIT(IF,false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPU_STI(Bitu opLen) {
|
||||
bool CPU_STI(void) {
|
||||
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return true;
|
||||
return CPU_PrepareException(13,0);
|
||||
} else {
|
||||
SETFLAGBIT(IF,true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPU_POPF(Bitu use32) {
|
||||
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
|
||||
return CPU_PrepareException(13,0);
|
||||
if (use32)
|
||||
CPU_SetFlagsd(CPU_Pop32());
|
||||
else CPU_SetFlagsw(CPU_Pop16());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CPU_PUSHF(Bitu use32) {
|
||||
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
|
||||
return CPU_PrepareException(13,0);
|
||||
if (use32)
|
||||
CPU_Push32(reg_flags);
|
||||
else CPU_Push16(reg_flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
class TaskStateSegment {
|
||||
public:
|
||||
TaskStateSegment() {
|
||||
|
@ -170,7 +186,7 @@ enum TSwitchType {
|
|||
TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET
|
||||
};
|
||||
|
||||
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
|
||||
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) {
|
||||
TaskStateSegment new_tss;
|
||||
if (!new_tss.SetSelector(new_tss_selector))
|
||||
E_Exit("Illegal TSS for switch");
|
||||
|
@ -185,7 +201,7 @@ bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
|
|||
Bitu new_ldt;
|
||||
if (cpu_tss.is386) {
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),reg_flags);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),reg_eip);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),old_eip);
|
||||
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx);
|
||||
|
@ -290,23 +306,31 @@ doconforming:
|
|||
return true;
|
||||
}
|
||||
|
||||
void CPU_StartException(void) {
|
||||
CPU_Interrupt(cpu.exception.which,CPU_INT_EXCEPTION | ((cpu.exception.which>=8) ? CPU_INT_HAS_ERROR : 0));
|
||||
}
|
||||
|
||||
void CPU_SetupException(Bitu which,Bitu error) {
|
||||
cpu.exception.which=which;
|
||||
cpu.exception.error=error;
|
||||
bool CPU_IO_Exception(Bitu port,Bitu size) {
|
||||
if (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM))) {
|
||||
if (!cpu_tss.is386) goto doexception;
|
||||
PhysPt where=cpu_tss.base+0x66;
|
||||
Bitu ofs=mem_readw(where);
|
||||
if (ofs>cpu_tss.limit) goto doexception;
|
||||
where=cpu_tss.base+ofs+(port/8);
|
||||
Bitu map=mem_readw(where);
|
||||
Bitu mask=(0xffff>>(16-size)) << (port&7);
|
||||
if (map & mask) goto doexception;
|
||||
}
|
||||
return false;
|
||||
doexception:
|
||||
LOG_MSG("Exception");
|
||||
return CPU_PrepareException(13,0);
|
||||
}
|
||||
|
||||
void CPU_Exception(Bitu which,Bitu error ) {
|
||||
// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags);
|
||||
CPU_SetupException(which,error);
|
||||
CPU_StartException();
|
||||
LOG_MSG("Exception %d error %x",which,error);
|
||||
cpu.exception.error=error;
|
||||
CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip);
|
||||
}
|
||||
|
||||
Bit8u lastint;
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
|
||||
lastint=num;
|
||||
#if C_DEBUG
|
||||
switch (num) {
|
||||
|
@ -324,10 +348,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
|||
};
|
||||
#endif
|
||||
if (!cpu.pmode) {
|
||||
/* Save everything on a 16-bit stack */
|
||||
/* Save everything on a 16-bit stack */
|
||||
CPU_Push16(reg_flags & 0xffff);
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
SETFLAGBIT(IF,false);
|
||||
SETFLAGBIT(TF,false);
|
||||
/* Get the new CS:IP from vector table */
|
||||
|
@ -345,7 +369,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
|||
if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) {
|
||||
// LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12);
|
||||
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
}
|
||||
|
@ -354,7 +377,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
|||
//TODO Check for software interrupt and check gate's dpl<cpl
|
||||
cpu.idt.GetDescriptor(num<<3,gate);
|
||||
if (type&CPU_INT_SOFTWARE && gate.DPL()<cpu.cpl) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,num*8+2);
|
||||
return;
|
||||
}
|
||||
|
@ -419,12 +441,12 @@ do_interrupt:
|
|||
if (gate.Type() & 0x8) { /* 32-bit Gate */
|
||||
CPU_Push32(reg_flags);
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error);
|
||||
} else { /* 16-bit gate */
|
||||
CPU_Push16(reg_flags & 0xffff);
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error);
|
||||
}
|
||||
break;
|
||||
|
@ -444,7 +466,7 @@ do_interrupt:
|
|||
return;
|
||||
}
|
||||
case DESC_TASK_GATE:
|
||||
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT);
|
||||
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) {
|
||||
//TODO Be sure about this, seems somewhat unclear
|
||||
if (cpu_tss.is386) CPU_Push32(cpu.exception.error);
|
||||
|
@ -459,7 +481,7 @@ do_interrupt:
|
|||
return ; // make compiler happy
|
||||
}
|
||||
|
||||
void CPU_IRET(bool use32,Bitu opLen) {
|
||||
void CPU_IRET(bool use32,Bitu oldeip) {
|
||||
if (!cpu.pmode) { /* RealMode IRET */
|
||||
realmode_iret:
|
||||
if (use32) {
|
||||
|
@ -476,7 +498,6 @@ realmode_iret:
|
|||
} else { /* Protected mode IRET */
|
||||
if (reg_flags & FLAG_VM) {
|
||||
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
} else goto realmode_iret;
|
||||
|
@ -488,7 +509,7 @@ realmode_iret:
|
|||
if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set");
|
||||
if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS");
|
||||
Bitu back_link=cpu_tss.Get_back();
|
||||
CPU_SwitchTask(back_link,TSwitch_IRET);
|
||||
CPU_SwitchTask(back_link,TSwitch_IRET,oldeip);
|
||||
return;
|
||||
}
|
||||
Bitu n_cs_sel,n_eip,n_flags;
|
||||
|
@ -595,7 +616,7 @@ realmode_iret:
|
|||
}
|
||||
}
|
||||
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
if (!use32) {
|
||||
reg_eip=offset&0xffff;
|
||||
|
@ -610,7 +631,6 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
|||
Descriptor desc;
|
||||
cpu.gdt.GetDescriptor(selector,desc);
|
||||
if (!desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
|
@ -635,7 +655,7 @@ CODE_jmp:
|
|||
if (desc.DPL()<cpu.cpl) E_Exit("JMP:TSS:dpl<cpl");
|
||||
if (desc.DPL()<rpl) E_Exit("JMP:TSS:dpl<rpl");
|
||||
LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector);
|
||||
CPU_SwitchTask(selector,TSwitch_JMP);
|
||||
CPU_SwitchTask(selector,TSwitch_JMP,oldeip);
|
||||
break;
|
||||
default:
|
||||
E_Exit("JMP Illegal descriptor type %X",desc.Type());
|
||||
|
@ -646,15 +666,15 @@ CODE_jmp:
|
|||
|
||||
|
||||
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
if (!use32) {
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
reg_eip=offset&0xffff;
|
||||
} else {
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
reg_eip=offset;
|
||||
}
|
||||
cpu.code.big=false;
|
||||
|
@ -665,7 +685,6 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
|||
Bitu rpl=selector & 3;
|
||||
cpu.gdt.GetDescriptor(selector,call);
|
||||
if (!call.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
|
@ -684,11 +703,11 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
|||
call_code:
|
||||
if (!use32) {
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
reg_eip=offset & 0xffff;
|
||||
} else {
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
reg_eip=offset;
|
||||
}
|
||||
Segs.phys[cs]=call.GetBase();
|
||||
|
@ -704,7 +723,6 @@ call_code:
|
|||
Bitu n_cs_sel=call.GetSelector();
|
||||
if (!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc)) E_Exit("Call:Gate:Invalid CS selector.");
|
||||
if (!n_cs_desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
|
@ -738,7 +756,7 @@ call_code:
|
|||
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
|
||||
CPU_Push32(mem_readd(o_stack+i*4));
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
} else {
|
||||
CPU_Push16(o_ss); //save old stack
|
||||
CPU_Push16(o_esp);
|
||||
|
@ -746,7 +764,7 @@ call_code:
|
|||
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
|
||||
CPU_Push16(mem_readw(o_stack+i*2));
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_eip);
|
||||
CPU_Push16(oldeip);
|
||||
}
|
||||
|
||||
cpu.cpl = n_cs_desc.DPL();
|
||||
|
@ -770,7 +788,7 @@ call_gate_same_privilege:
|
|||
if (call.DPL()<cpu.cpl) E_Exit("CALL:TSS:dpl<cpl");
|
||||
if (call.DPL()<rpl) E_Exit("CALL:TSS:dpl<rpl");
|
||||
LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
|
||||
CPU_SwitchTask(selector,TSwitch_CALL_INT);
|
||||
CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
|
||||
break;
|
||||
default:
|
||||
E_Exit("CALL:Descriptor type %x unsupported",call.Type());
|
||||
|
@ -781,7 +799,7 @@ call_gate_same_privilege:
|
|||
}
|
||||
|
||||
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
Bitu new_ip,new_cs;
|
||||
if (!use32) {
|
||||
|
@ -804,14 +822,12 @@ void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
|
|||
Descriptor desc;
|
||||
Bitu rpl=selector & 3;
|
||||
if (rpl<cpu.cpl) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
cpu.gdt.GetDescriptor(selector,desc);
|
||||
|
||||
if (!desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
};
|
||||
|
@ -934,9 +950,8 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
|
|||
case 0:
|
||||
{
|
||||
Bitu changed=cpu.cr0 ^ value;
|
||||
if (!changed) return true;
|
||||
if (!changed) return false;
|
||||
cpu.cr0=value;
|
||||
//TODO Maybe always first change to core_full for a change to cr0
|
||||
if (value & CR0_PROTECTION) {
|
||||
cpu.pmode=true;
|
||||
LOG(LOG_CPU,LOG_NORMAL)("Protected mode");
|
||||
|
@ -946,7 +961,7 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
|
|||
PAGING_Enable(false);
|
||||
LOG(LOG_CPU,LOG_NORMAL)("Real mode");
|
||||
}
|
||||
return false; //Only changes with next CS change
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
paging.cr2=value;
|
||||
|
@ -981,11 +996,12 @@ void CPU_SMSW(Bitu & word) {
|
|||
word=cpu.cr0;
|
||||
}
|
||||
|
||||
bool CPU_LMSW(Bitu word) {
|
||||
Bitu CPU_LMSW(Bitu word) {
|
||||
word&=0xf;
|
||||
if (cpu.cr0 & 1) word|=1;
|
||||
word|=(cpu.cr0&0xfffffff0);
|
||||
return CPU_SET_CRX(0,word);
|
||||
CPU_SET_CRX(0,word);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
|
||||
|
@ -1166,13 +1182,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
|
|||
if (!desc.saved.seg.p) {
|
||||
if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present.");
|
||||
// Throw Exception 0x0B - Segment not present
|
||||
CPU_SetupException(0x0B,value & 0xfffc);
|
||||
return true;
|
||||
return CPU_PrepareException(0x0B,value & 0xfffc);
|
||||
} else if (seg==ss) {
|
||||
// Stack segment loaded with illegal segment ?
|
||||
if ((desc.saved.seg.type<DESC_DATA_EU_RO_NA) || (desc.saved.seg.type>DESC_DATA_ED_RW_A)) {
|
||||
CPU_SetupException(0x0D,value & 0xfffc);
|
||||
return true;
|
||||
return CPU_PrepareException(0x0D,value & 0xfffc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1191,6 +1205,14 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
|
|||
}
|
||||
}
|
||||
|
||||
bool CPU_PopSeg(SegNames seg,bool use32) {
|
||||
Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
|
||||
if (CPU_SetSegGeneral(seg,val)) return true;
|
||||
Bitu addsp=2 << use32;
|
||||
reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPU_CPUID(void) {
|
||||
switch (reg_eax) {
|
||||
case 0: /* Vendor ID String and maximum level? */
|
||||
|
@ -1221,12 +1243,12 @@ static Bits HLT_Decode(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CPU_HLT(Bitu opLen) {
|
||||
void CPU_HLT(Bitu oldeip) {
|
||||
if (cpu.cpl) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
}
|
||||
reg_eip=oldeip;
|
||||
CPU_Cycles=0;
|
||||
cpu.hlt.cs=SegValue(cs);
|
||||
cpu.hlt.eip=reg_eip;
|
||||
|
@ -1235,6 +1257,38 @@ void CPU_HLT(Bitu opLen) {
|
|||
return;
|
||||
}
|
||||
|
||||
void CPU_ENTER(bool use32,Bitu bytes,Bitu level) {
|
||||
level&=0x1f;
|
||||
Bitu sp_index=reg_esp&cpu.stack.mask;
|
||||
Bitu bp_index=reg_ebp&cpu.stack.mask;
|
||||
if (!use32) {
|
||||
sp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,reg_bp);
|
||||
reg_bp=(Bit16u)(reg_esp-2);
|
||||
if (level) {
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
sp_index-=2;bp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,mem_readw(SegPhys(ss)+bp_index));
|
||||
}
|
||||
sp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,reg_bp);
|
||||
}
|
||||
} else {
|
||||
sp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
|
||||
reg_ebp=(reg_esp-4);
|
||||
if (level) {
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
sp_index-=4;bp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,mem_readd(SegPhys(ss)+bp_index));
|
||||
}
|
||||
sp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
|
||||
}
|
||||
}
|
||||
sp_index-=bytes;
|
||||
reg_esp=(reg_esp&~cpu.stack.mask)|((sp_index)&cpu.stack.mask);
|
||||
}
|
||||
|
||||
extern void GFX_SetTitle(Bits cycles ,Bits frameskip);
|
||||
static void CPU_CycleIncrease(void) {
|
||||
|
@ -1263,7 +1317,6 @@ static void CPU_CycleDecrease(void) {
|
|||
GFX_SetTitle(CPU_CycleMax,-1);
|
||||
}
|
||||
|
||||
|
||||
void CPU_Init(Section* sec) {
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
reg_eax=0;
|
||||
|
|
Loading…
Add table
Reference in a new issue