Fixed a lot of code duplication and possible bug with oncorrect implementation of repeat speedup in 64-bit guest

This commit is contained in:
Stanislav Shwartsman 2007-12-17 21:13:55 +00:00
parent fe2e0525da
commit d032a30429
2 changed files with 159 additions and 193 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: io.cc,v 1.43 2007-12-16 21:03:45 sshwarts Exp $
// $Id: io.cc,v 1.44 2007-12-17 21:13:55 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -329,12 +329,10 @@ void BX_CPU_C::INSB_YbDX(bxInstruction_c *i)
{
Bit8u value8=0;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
BX_DEBUG(("INSB_YbDX: I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
#if BX_SUPPORT_X86_64
if (i->as64L()) {
@ -391,40 +389,54 @@ void BX_CPU_C::INSB_YbDX(bxInstruction_c *i)
// input word from port to string
void BX_CPU_C::INSW_YwDX(bxInstruction_c *i)
{
bx_address edi;
unsigned int incr = 2;
bx_address rdi;
Bit32u incr = 2;
Bit16u value16=0;
#if BX_SUPPORT_X86_64
if (i->as64L())
edi = RDI;
if (i->as64L()) {
rdi = RDI;
// Write a zero to memory, to trigger any segment or page
// faults before reading from IO port.
write_virtual_word(BX_SEG_REG_ES, rdi, &value16);
value16 = BX_INP(DX, 2);
/* no seg override allowed */
write_virtual_word(BX_SEG_REG_ES, rdi, &value16);
if (BX_CPU_THIS_PTR get_DF())
rdi -= 2;
else
rdi += 2;
RDI = rdi;
}
else
#endif
{
if (i->as32L())
edi = EDI;
rdi = EDI;
else
edi = DI;
Bit16u value16=0;
rdi = DI;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time.
*/
if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) {
if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
{
Bit32u wordCount;
#if BX_SUPPORT_X86_64
if (i->as64L())
wordCount = RCX; // Truncated to 32bits. (we're only doing 1 page)
else
#endif
if (i->as32L())
wordCount = ECX;
else
wordCount = CX;
BX_ASSERT(wordCount > 0);
wordCount = FastRepINSW(i, edi, DX, wordCount);
wordCount = FastRepINSW(i, rdi, DX, wordCount);
if (wordCount)
{
// Decrement the ticks count by the number of iterations, minus
@ -433,11 +445,6 @@ void BX_CPU_C::INSW_YwDX(bxInstruction_c *i)
// don't roll it under zero.
BX_TICKN(wordCount-1);
#if BX_SUPPORT_X86_64
if (i->as64L())
RCX -= (wordCount-1);
else
#endif
if (i->as32L())
RCX = ECX - (wordCount-1);
else
@ -451,27 +458,17 @@ void BX_CPU_C::INSW_YwDX(bxInstruction_c *i)
// Write a zero to memory, to trigger any segment or page
// faults before reading from IO port.
write_virtual_word(BX_SEG_REG_ES, edi, &value16);
write_virtual_word(BX_SEG_REG_ES, rdi, &value16);
value16 = BX_INP(DX, 2);
/* no seg override allowed */
write_virtual_word(BX_SEG_REG_ES, edi, &value16);
incr = 2;
write_virtual_word(BX_SEG_REG_ES, rdi, &value16);
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
doIncr:
#endif
#if BX_SUPPORT_X86_64
if (i->as64L()) {
if (BX_CPU_THIS_PTR get_DF())
RDI = RDI - incr;
else
RDI = RDI + incr;
}
else
#endif
if (i->as32L()) {
if (BX_CPU_THIS_PTR get_DF())
RDI = EDI - incr;
@ -480,51 +477,50 @@ doIncr:
}
else {
if (BX_CPU_THIS_PTR get_DF())
DI = DI - incr;
DI -= incr;
else
DI = DI + incr;
DI += incr;
}
}
}
// input doubleword from port to string
void BX_CPU_C::INSD_YdDX(bxInstruction_c *i)
{
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
BX_DEBUG(("INSD_YdDX: I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
bx_address edi;
bx_address rdi;
#if BX_SUPPORT_X86_64
if (i->as64L())
edi = RDI;
rdi = RDI;
else
#endif
if (i->as32L())
edi = EDI;
rdi = EDI;
else
edi = DI;
rdi = DI;
Bit32u value32=0;
// Write a zero to memory, to trigger any segment or page
// faults before reading from IO port.
write_virtual_dword(BX_SEG_REG_ES, edi, &value32);
write_virtual_dword(BX_SEG_REG_ES, rdi, &value32);
value32 = BX_INP(DX, 4);
/* no seg override allowed */
write_virtual_dword(BX_SEG_REG_ES, edi, &value32);
write_virtual_dword(BX_SEG_REG_ES, rdi, &value32);
#if BX_SUPPORT_X86_64
if (i->as64L()) {
if (BX_CPU_THIS_PTR get_DF())
RDI = RDI - 4;
RDI -= 4;
else
RDI = RDI + 4;
RDI += 4;
}
else
#endif
@ -536,9 +532,9 @@ void BX_CPU_C::INSD_YdDX(bxInstruction_c *i)
}
else {
if (BX_CPU_THIS_PTR get_DF())
DI = DI - 4;
DI -= 4;
else
DI = DI + 4;
DI += 4;
}
}
@ -570,12 +566,10 @@ void BX_CPU_C::OUTSB_DXXb(bxInstruction_c *i)
Bit8u value8;
bx_address esi;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
#if BX_SUPPORT_X86_64
if (i->as64L())
@ -618,14 +612,12 @@ void BX_CPU_C::OUTSB_DXXb(bxInstruction_c *i)
void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i)
{
bx_address esi;
unsigned incr = 2;
Bit32u incr = 2;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
#if BX_SUPPORT_X86_64
if (i->as64L())
@ -711,12 +703,10 @@ void BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i)
// output doubleword string to port
void BX_CPU_C::OUTSD_DXXd(bxInstruction_c *i)
{
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
bx_address esi;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: io_pro.cc,v 1.25 2007-11-29 21:45:10 sshwarts Exp $
// $Id: io_pro.cc,v 1.26 2007-12-17 21:13:55 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -35,32 +35,22 @@
Bit16u BX_CPP_AttrRegparmN(1)
BX_CPU_C::inp16(Bit16u addr)
{
Bit16u ret16;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 2)) {
BX_DEBUG(("inp16(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
ret16 = BX_INP(addr, 2);
Bit16u ret16 = BX_INP(addr, 2);
return ret16;
}
void BX_CPP_AttrRegparmN(2)
BX_CPU_C::outp16(Bit16u addr, Bit16u value)
{
/* If CPL <= IOPL, then all IO addresses are accessible.
* Otherwise, must check the IO permission map on >286.
* On the 286, there is no IO permissions map */
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 2)) {
BX_DEBUG(("outp16(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
BX_OUTP(addr, value, 2);
}
@ -68,32 +58,22 @@ BX_CPU_C::outp16(Bit16u addr, Bit16u value)
Bit32u BX_CPP_AttrRegparmN(1)
BX_CPU_C::inp32(Bit16u addr)
{
Bit32u ret32;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 4)) {
BX_DEBUG(("inp32(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
ret32 = BX_INP(addr, 4);
Bit32u ret32 = BX_INP(addr, 4);
return ret32;
}
void BX_CPP_AttrRegparmN(2)
BX_CPU_C::outp32(Bit16u addr, Bit32u value)
{
/* If CPL <= IOPL, then all IO addresses are accessible.
* Otherwise, must check the IO permission map on >286.
* On the 286, there is no IO permissions map */
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 4)) {
BX_DEBUG(("outp32(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
BX_OUTP(addr, value, 4);
}
@ -101,33 +81,22 @@ BX_CPU_C::outp32(Bit16u addr, Bit32u value)
Bit8u BX_CPP_AttrRegparmN(1)
BX_CPU_C::inp8(Bit16u addr)
{
Bit8u ret8;
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 1)) {
BX_DEBUG(("inp8(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
ret8 = BX_INP(addr, 1);
Bit8u ret8 = BX_INP(addr, 1);
return ret8;
}
void BX_CPP_AttrRegparmN(2)
BX_CPU_C::outp8(Bit16u addr, Bit8u value)
{
/* If CPL <= IOPL, then all IO addresses are accessible.
* Otherwise, must check the IO permission map on >286.
* On the 286, there is no IO permissions map */
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL()))) {
if (! BX_CPU_THIS_PTR allow_io(addr, 1)) {
BX_DEBUG(("outp8(): I/O access not allowed !"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
BX_OUTP(addr, value, 1);
}
@ -136,6 +105,12 @@ bx_bool BX_CPU_C::allow_io(Bit16u addr, unsigned len)
{
Bit16u io_base, permission16;
/* If CPL <= IOPL, then all IO addresses are accessible.
* Otherwise, must check the IO permission map on >286.
* On the 286, there is no IO permissions map */
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL>BX_CPU_THIS_PTR get_IOPL())))
{
if (BX_CPU_THIS_PTR tr.cache.valid==0 ||
BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS)
{
@ -172,6 +147,7 @@ bx_bool BX_CPU_C::allow_io(Bit16u addr, unsigned len)
return(0);
permission16 >>= 1;
}
}
return(1);
}