1
0
Fork 0

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:
Sjoerd van der Berg 2004-04-22 22:40:46 +00:00
parent 2bccfd7a22
commit 5460def634
18 changed files with 589 additions and 742 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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 },

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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; \
} \

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;

View file

@ -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) \
{ \

View file

@ -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;