Fixes in zero upper ECX

This commit is contained in:
Stanislav Shwartsman 2007-09-25 16:11:32 +00:00
parent 6b86091441
commit e812f81e7b
9 changed files with 61 additions and 46 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.172 2007-07-09 15:16:10 sshwarts Exp $
// $Id: cpu.cc,v 1.173 2007-09-25 16:11:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -116,6 +116,7 @@ static unsigned iCacheMisses=0;
#if BX_SUPPORT_X86_64==0
#define RIP EIP
#define RSP ESP
#define RCX ECX
#endif
BX_CPP_INLINE bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased)
@ -330,7 +331,7 @@ void BX_CPU_C::repeat(bxInstruction_c *i, BxExecutePtr_t execute)
if (ECX != 0) {
BX_CPU_CALL_METHOD(execute, (i));
BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i);
ECX --;
RCX = ECX - 1;
}
if (ECX == 0) return;
}
@ -381,7 +382,7 @@ void BX_CPU_C::repeat_ZFL(bxInstruction_c *i, BxExecutePtr_t execute)
if (ECX != 0) {
BX_CPU_CALL_METHOD(execute, (i));
BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i);
ECX --;
RCX = ECX - 1;
}
if ((i->repUsedValue()==3) && (get_ZF()==0)) return;
if ((i->repUsedValue()==2) && (get_ZF()!=0)) return;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer64.cc,v 1.47 2006-06-09 22:29:06 sshwarts Exp $
// $Id: ctrl_xfer64.cc,v 1.48 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -330,7 +330,8 @@ void BX_CPU_C::LOOPNE64_Jb(bxInstruction_c *i)
}
}
else {
if (((--ECX) != 0) && (get_ZF()==0)) {
RCX = ECX - 1;
if (RCX != 0 && (get_ZF()==0)) {
branch_near64(i);
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP);
return;
@ -343,14 +344,15 @@ void BX_CPU_C::LOOPNE64_Jb(bxInstruction_c *i)
void BX_CPU_C::LOOPE64_Jb(bxInstruction_c *i)
{
if (i->as64L()) {
if (((--RCX)!=0) && (get_ZF())) {
if (((--RCX)!=0) && get_ZF()) {
branch_near64(i);
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP);
return;
}
}
else {
if (((--ECX)!=0) && get_ZF()) {
RCX = ECX - 1;
if (RCX != 0 && get_ZF()) {
branch_near64(i);
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP);
return;
@ -370,7 +372,8 @@ void BX_CPU_C::LOOP64_Jb(bxInstruction_c *i)
}
}
else {
if ((--ECX) != 0) {
RCX = ECX - 1;
if (RCX != 0) {
branch_near64(i);
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, RIP);
return;

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: ctrl_xfer_pro.cc,v 1.57 2007-09-10 20:47:08 sshwarts Exp $
// $Id: ctrl_xfer_pro.cc,v 1.58 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -49,8 +49,7 @@ void BX_CPU_C::check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_
}
#if BX_SUPPORT_X86_64
if (descriptor->u.segment.l)
{
if (descriptor->u.segment.l) {
if (! BX_CPU_THIS_PTR efer.lma) {
BX_PANIC(("check_cs: attempt to jump to long mode without enabling EFER.LMA !"));
}
@ -111,8 +110,11 @@ BX_CPU_C::load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cp
loadSRegLMNominal(BX_SEG_REG_CS, selector->value, cpl);
}
else {
BX_DEBUG(("Compatibility Mode Activated"));
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
BX_DEBUG(("Compatibility Mode Activated"));
if (BX_CPU_THIS_PTR dword.rip_upper != 0) {
BX_PANIC(("handleCpuModeChange: leaving long mode with RIP upper != 0 !"));
}
}
}
#endif
@ -178,8 +180,7 @@ void BX_CPU_C::branch_far64(bx_selector_t *selector,
bx_descriptor_t *descriptor, bx_address rip, Bit8u cpl)
{
#if BX_SUPPORT_X86_64
if (descriptor->u.segment.l)
{
if (descriptor->u.segment.l) {
if (! IsCanonical(rip)) {
BX_ERROR(("branch_far: canonical RIP violation"));
exception(BX_GP_EXCEPTION, 0, 0);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: io.cc,v 1.38 2007-07-09 15:16:12 sshwarts Exp $
// $Id: io.cc,v 1.39 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -423,9 +423,9 @@ void BX_CPU_C::INSW_YwDX(bxInstruction_c *i)
else
#endif
if (i->as32L())
ECX -= (wordCount-1);
RCX = ECX - (wordCount-1);
else
CX -= (wordCount-1);
CX -= (wordCount-1);
incr = wordCount << 1; // count * 2.
goto doIncr;
@ -658,9 +658,9 @@ void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i)
else
#endif
if (i->as32L())
ECX -= (wordCount-1);
RCX = ECX - (wordCount-1);
else
CX -= (wordCount-1);
CX -= (wordCount-1);
incr = wordCount << 1; // count * 2.
goto doIncr;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.169 2007-09-20 17:33:35 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.170 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1223,6 +1223,9 @@ void BX_CPU_C::handleCpuModeChange(void)
}
else {
BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT;
if (BX_CPU_THIS_PTR dword.rip_upper != 0) {
BX_PANIC(("handleCpuModeChange: leaving long mode with RIP upper != 0 !"));
}
BX_DEBUG(("Compatibility Mode Activated"));
}
}
@ -1309,6 +1312,10 @@ void BX_CPU_C::SetCR0(Bit32u val_32)
}
}
else if (prev_pg==1 && ! BX_CPU_THIS_PTR cr0.get_PG()) {
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
BX_ERROR(("SetCR0: attempt to leave 64 bit mode directly to legacy mode !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
if (BX_CPU_THIS_PTR efer.lma) {
if (BX_CPU_THIS_PTR dword.rip_upper != 0) {
BX_PANIC(("SetCR0: attempt to leave x86-64 LONG mode with RIP upper != 0 !!!"));
@ -1433,8 +1440,8 @@ void BX_CPU_C::RDPMC(bxInstruction_c *i)
// writes. Misaligned etc... But to monitor bochs, this
// is easier done from the host.
EAX = 0;
EDX = 0; // if P4 and ECX & 0x10000000, then always 0 (short read 32 bits)
RAX = 0;
RDX = 0; // if P4 and ECX & 0x10000000, then always 0 (short read 32 bits)
BX_ERROR(("RDPMC: Performance Counters Support not reasonably implemented yet"));
} else {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: protect_ctrl.cc,v 1.58 2007-03-23 14:50:45 sshwarts Exp $
// $Id: protect_ctrl.cc,v 1.59 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -452,6 +452,13 @@ void BX_CPU_C::LTR_Ew(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
}
#if BX_SUPPORT_X86_64
if (long_mode() && descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) {
BX_ERROR(("LTR: doesn't point to an available TSS386 descriptor in long mode!"));
exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
}
#endif
/* #NP(selector) if TSS descriptor is not present */
if (! IS_PRESENT(descriptor)) {
BX_ERROR(("LTR: LDT descriptor not present!"));

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: ret_far.cc,v 1.9 2007-02-03 21:36:40 sshwarts Exp $
// $Id: ret_far.cc,v 1.10 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -68,13 +68,8 @@ BX_CPU_C::return_protected(bxInstruction_c *i, Bit16u pop_bytes)
#if BX_SUPPORT_X86_64
if (i->os64L()) {
/* operand size=64: 2nd qword on stack must be within stack limits,
* else #SS(0); */
if (!can_pop(16))
{
BX_ERROR(("return_protected: 2rd qword not in stack limits"));
exception(BX_SS_EXCEPTION, 0, 0);
}
/* operand size=64: in long mode 1st and 2nd quadword on the stack
must be in canonical address space */
read_virtual_word (BX_SEG_REG_SS, temp_RSP + 8, &raw_cs_selector);
read_virtual_qword(BX_SEG_REG_SS, temp_RSP + 0, &return_RIP);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: segment_ctrl_pro.cc,v 1.70 2007-09-10 20:47:08 sshwarts Exp $
// $Id: segment_ctrl_pro.cc,v 1.71 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -38,10 +38,16 @@ BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value)
{
if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS])
{
bx_selector_t ss_selector;
bx_descriptor_t descriptor;
Bit32u dword1, dword2;
parse_selector(new_value, &ss_selector);
if ((new_value & 0xfffc) == 0) { /* null selector */
#if BX_SUPPORT_X86_64
// allow SS = 0 in 64 bit mode with cpl != 3
if (BX_CPU_THIS_PTR efer.lma && CPL != 3) {
// allow SS = 0 in 64 bit mode only with cpl != 3 and rpl=cpl
if (Is64BitMode() && CPL != 3 && ss_selector.rpl == CPL) {
seg->selector.index = 0;
seg->selector.ti = 0;
seg->selector.rpl = 0;
@ -50,15 +56,10 @@ BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value)
return;
}
#endif
BX_ERROR(("load_seg_reg(SS): new_value == 0"));
exception(BX_GP_EXCEPTION, 0, 0);
BX_ERROR(("load_seg_reg(SS): loading null selector"));
exception(BX_GP_EXCEPTION, new_value & 0xfffc, 0);
}
bx_descriptor_t descriptor;
Bit32u dword1, dword2;
bx_selector_t ss_selector;
parse_selector(new_value, &ss_selector);
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
/* selector's RPL must = CPL, else #GP(selector) */
@ -257,7 +258,7 @@ void BX_CPU_C::loadSRegLMNominal(unsigned segI, unsigned selector, unsigned dpl)
// of type bx_addr and be maxed to 64bits, not 32.
seg->cache.u.segment.limit_scaled = 0xffffffff;
seg->cache.valid = 1;
seg->cache.dpl = dpl; // (KPL) Not sure if we need this.
seg->cache.dpl = dpl;
seg->selector.value = selector;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: string.cc,v 1.37 2007-07-09 15:16:14 sshwarts Exp $
// $Id: string.cc,v 1.38 2007-09-25 16:11:32 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1049,7 +1049,7 @@ void BX_CPU_C::MOVSD_XdYd(bxInstruction_c *i)
// Decrement eCX. Note, the main loop will decrement 1 also, so
// decrement by one less than expected, like the case above.
ECX -= (dwordCount-1);
RCX = ECX - (dwordCount-1);
incr = dwordCount << 2; // count * 4
goto doIncr32;
@ -1843,9 +1843,9 @@ void BX_CPU_C::STOSB_YbAL(bxInstruction_c *i)
// Decrement eCX. Note, the main loop will decrement 1 also, so
// decrement by one less than expected, like the case above.
if (i->as32L())
ECX -= (byteCount-1);
RCX = ECX - (byteCount-1);
else
CX -= (byteCount-1);
CX -= (byteCount-1);
incr = byteCount;
goto doIncr16;