From 1a355e270ec66972e9eb3b042b3d5389c93e5add Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Thu, 12 Jun 2008 20:12:25 +0000 Subject: [PATCH] split io repeat methods by address size --- bochs/cpu/cpu.h | 28 +- bochs/cpu/io.cc | 1002 ++++++++++++++++++++++++++++------------------- 2 files changed, 610 insertions(+), 420 deletions(-) diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index de1be9e80..938aa51d8 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.486 2008-06-12 19:14:39 sshwarts Exp $ +// $Id: cpu.h,v 1.487 2008-06-12 20:12:25 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1079,12 +1079,18 @@ public: // for now... BX_SMF void PUSH_Id(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void PUSH_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void INSB_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void INSW_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void INSD_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void OUTSB_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void OUTSW_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); - BX_SMF void OUTSD_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSB32_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSB16_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSW32_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSW16_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSD32_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSD16_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSB32_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSB16_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSW32_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSW16_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSD32_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSD16_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void REP_INSB_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void REP_INSW_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); @@ -2538,6 +2544,14 @@ public: // for now... BX_SMF void MOVSQ32_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSQ64_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSB64_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSW64_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void INSD64_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + + BX_SMF void OUTSB64_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSW64_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void OUTSD64_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); + BX_SMF void CALL_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void JMP_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); diff --git a/bochs/cpu/io.cc b/bochs/cpu/io.cc index 0721fa904..631eec45f 100644 --- a/bochs/cpu/io.cc +++ b/bochs/cpu/io.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: io.cc,v 1.60 2008-06-12 19:14:39 sshwarts Exp $ +// $Id: io.cc,v 1.61 2008-06-12 20:12:25 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -223,39 +223,23 @@ Bit32u BX_CPU_C::FastRepOUTSW(bxInstruction_c *i, unsigned srcSeg, bx_address sr void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSB_YbDX(bxInstruction_c *i) { - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB_YbDX); #if BX_SUPPORT_X86_64 + if (i->as64L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB64_YbDX); + } + else +#endif if (i->as32L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB32_YbDX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } -#endif -} - -void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSW_YwDX(bxInstruction_c *i) -{ - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW_YwDX); -#if BX_SUPPORT_X86_64 - if (i->as32L()) { - BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB16_YbDX); } -#endif } -void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSD_YdDX(bxInstruction_c *i) -{ - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD_YdDX); -#if BX_SUPPORT_X86_64 - if (i->as32L()) { - BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI - } -#endif -} - -// -// INSB/INSW/INSD methods -// - -void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB_YbDX(bxInstruction_c *i) +// 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB16_YbDX(bxInstruction_c *i) { Bit8u value8=0; @@ -264,458 +248,650 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB_YbDX(bxInstruction_c *i) exception(BX_GP_EXCEPTION, 0, 0); } -#if BX_SUPPORT_X86_64 - if (i->as64L()) { - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_byte_64(BX_SEG_REG_ES, RDI, value8); + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_byte_32(BX_SEG_REG_ES, DI, value8); - value8 = BX_INP(DX, 1); + value8 = BX_INP(DX, 1); - /* no seg override possible */ - write_virtual_byte_64(BX_SEG_REG_ES, RDI, value8); + /* no seg override possible */ + write_virtual_byte_32(BX_SEG_REG_ES, DI, value8); - if (BX_CPU_THIS_PTR get_DF()) - RDI--; - else - RDI++; - } + if (BX_CPU_THIS_PTR get_DF()) + DI--; else -#endif - if (i->as32L()) { - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_byte(BX_SEG_REG_ES, EDI, value8); - - value8 = BX_INP(DX, 1); - - /* no seg override possible */ - write_virtual_byte(BX_SEG_REG_ES, EDI, value8); - - if (BX_CPU_THIS_PTR get_DF()) { - RDI = EDI - 1; - } - else { - RDI = EDI + 1; - } - } - else { // 16-bit address size - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_byte_32(BX_SEG_REG_ES, DI, value8); - - value8 = BX_INP(DX, 1); - - /* no seg override possible */ - write_virtual_byte_32(BX_SEG_REG_ES, DI, value8); - - if (BX_CPU_THIS_PTR get_DF()) - DI--; - else - DI++; - } + DI++; } -// input word from port to string -void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW_YwDX(bxInstruction_c *i) +// 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB32_YbDX(bxInstruction_c *i) { - Bit16u value16=0; + Bit8u value8=0; -#if BX_SUPPORT_X86_64 - if (i->as64L()) { - Bit64u rdi = RDI; - - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_word_64(BX_SEG_REG_ES, rdi, value16); - - value16 = BX_INP(DX, 2); - - /* no seg override allowed */ - write_virtual_word_64(BX_SEG_REG_ES, rdi, value16); - - if (BX_CPU_THIS_PTR get_DF()) - rdi -= 2; - else - rdi += 2; - - RDI = rdi; - } - else -#endif - { - Bit32u edi; - Bit32u incr = 2; - - if (i->as32L()) - edi = EDI; - else - edi = 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) - { - Bit32u wordCount; - - if (i->as32L()) - wordCount = ECX; - else - wordCount = CX; - - BX_ASSERT(wordCount > 0); - - wordCount = FastRepINSW(i, edi, DX, wordCount); - if (wordCount) - { - // Decrement the ticks count by the number of iterations, minus - // one, since the main cpu loop will decrement one. Also, - // the count is predecremented before examined, so defintely - // don't roll it under zero. - BX_TICKN(wordCount-1); - - if (i->as32L()) - RCX = ECX - (wordCount-1); - else - CX -= (wordCount-1); - - incr = wordCount << 1; // count * 2. - goto doIncr; - } - } -#endif - - // 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); - - value16 = BX_INP(DX, 2); - - /* no seg override allowed */ - write_virtual_word(BX_SEG_REG_ES, edi, value16); - -#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0) -doIncr: -#endif - - if (i->as32L()) { - if (BX_CPU_THIS_PTR get_DF()) - RDI = EDI - incr; - else - RDI = EDI + incr; - } - else { - if (BX_CPU_THIS_PTR get_DF()) - DI -= incr; - else - DI += incr; - } - } -} - -// input doubleword from port to string -void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD_YdDX(bxInstruction_c *i) -{ - if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { - BX_DEBUG(("INSD_YdDX: I/O access not allowed !")); + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("INSB_YbDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0, 0); } + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_byte(BX_SEG_REG_ES, EDI, value8); + + value8 = BX_INP(DX, 1); + + /* no seg override possible */ + write_virtual_byte(BX_SEG_REG_ES, EDI, value8); + + if (BX_CPU_THIS_PTR get_DF()) { + RDI = EDI - 1; + } + else { + RDI = EDI + 1; + } +} + +#if BX_SUPPORT_X86_64 + +// 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB64_YbDX(bxInstruction_c *i) +{ + Bit8u value8=0; + + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("INSB_YbDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_byte_64(BX_SEG_REG_ES, RDI, value8); + + value8 = BX_INP(DX, 1); + + /* no seg override possible */ + write_virtual_byte_64(BX_SEG_REG_ES, RDI, value8); + + if (BX_CPU_THIS_PTR get_DF()) + RDI--; + else + RDI++; +} + +#endif + +void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSW_YwDX(bxInstruction_c *i) +{ #if BX_SUPPORT_X86_64 if (i->as64L()) { - Bit64u rdi = RDI; - - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_dword_64(BX_SEG_REG_ES, rdi, 0); - - Bit32u value32 = BX_INP(DX, 4); - - /* no seg override allowed */ - write_virtual_dword_64(BX_SEG_REG_ES, rdi, value32); - - if (BX_CPU_THIS_PTR get_DF()) - rdi -= 4; - else - rdi += 4; - - RDI = rdi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW64_YwDX); } else #endif if (i->as32L()) { - Bit32u edi = EDI; - - // 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, 0); - - Bit32u value32 = BX_INP(DX, 4); - - /* no seg override allowed */ - write_virtual_dword(BX_SEG_REG_ES, edi, value32); - - if (BX_CPU_THIS_PTR get_DF()) - edi -= 4; - else - edi += 4; - - RDI = edi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW32_YwDX); + BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } - else { // 16-bit address size - Bit16u di = DI; - - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_dword_32(BX_SEG_REG_ES, di, 0); - - Bit32u value32 = BX_INP(DX, 4); - - /* no seg override allowed */ - write_virtual_dword_32(BX_SEG_REG_ES, di, value32); - - if (BX_CPU_THIS_PTR get_DF()) - di -= 4; - else - di += 4; - - DI = di; + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW16_YwDX); } } +// 16-bit operand size, 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW16_YwDX(bxInstruction_c *i) +{ + Bit16u value16=0; + Bit16u di = DI; + unsigned incr = 2; + + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("INSW16_YwDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + +#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) + { + Bit32u wordCount = CX; + BX_ASSERT(wordCount > 0); + wordCount = FastRepINSW(i, di, DX, wordCount); + if (wordCount) { + // Decrement the ticks count by the number of iterations, minus + // one, since the main cpu loop will decrement one. Also, + // the count is predecremented before examined, so defintely + // don't roll it under zero. + BX_TICKN(wordCount-1); + CX -= (wordCount-1); + incr = wordCount << 1; // count * 2 + } + else { + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_word_32(BX_SEG_REG_ES, di, value16); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word_32(BX_SEG_REG_ES, di, value16); + } + } + else +#endif + { + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_word_32(BX_SEG_REG_ES, di, value16); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word_32(BX_SEG_REG_ES, di, value16); + } + + if (BX_CPU_THIS_PTR get_DF()) + DI -= incr; + else + DI += incr; +} + +// 16-bit operand size, 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW32_YwDX(bxInstruction_c *i) +{ + Bit16u value16=0; + Bit32u edi = EDI; + unsigned incr = 2; + + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("INSW32_YwDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + +#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) + { + Bit32u wordCount = ECX; + BX_ASSERT(wordCount > 0); + wordCount = FastRepINSW(i, edi, DX, wordCount); + if (wordCount) { + // Decrement the ticks count by the number of iterations, minus + // one, since the main cpu loop will decrement one. Also, + // the count is predecremented before examined, so defintely + // don't roll it under zero. + BX_TICKN(wordCount-1); + RCX = ECX - (wordCount-1); + incr = wordCount << 1; // count * 2. + } + else { + // 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); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word(BX_SEG_REG_ES, edi, value16); + } + } + else +#endif + { + // 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); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word(BX_SEG_REG_ES, edi, value16); + } + + if (BX_CPU_THIS_PTR get_DF()) + RDI = EDI - incr; + else + RDI = EDI + incr; +} + +#if BX_SUPPORT_X86_64 + +// 16-bit operand size, 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW64_YwDX(bxInstruction_c *i) +{ + Bit16u value16=0; + Bit64u rdi = RDI; + + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("INSW64_YwDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_word_64(BX_SEG_REG_ES, rdi, value16); + + value16 = BX_INP(DX, 2); + + /* no seg override allowed */ + write_virtual_word_64(BX_SEG_REG_ES, rdi, value16); + + if (BX_CPU_THIS_PTR get_DF()) + rdi -= 2; + else + rdi += 2; + + RDI = rdi; +} + +#endif + +void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSD_YdDX(bxInstruction_c *i) +{ +#if BX_SUPPORT_X86_64 + if (i->as64L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD64_YdDX); + } + else +#endif + if (i->as32L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD32_YdDX); + BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI + } + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD16_YdDX); + } +} + +// 32-bit operand size, 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD16_YdDX(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("INSD16_YdDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit16u di = DI; + + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_dword_32(BX_SEG_REG_ES, di, 0); + + Bit32u value32 = BX_INP(DX, 4); + + /* no seg override allowed */ + write_virtual_dword_32(BX_SEG_REG_ES, di, value32); + + if (BX_CPU_THIS_PTR get_DF()) + di -= 4; + else + di += 4; + + DI = di; +} + +// 32-bit operand size, 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD32_YdDX(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("INSD32_YdDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit32u edi = EDI; + + // 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, 0); + + Bit32u value32 = BX_INP(DX, 4); + + /* no seg override allowed */ + write_virtual_dword(BX_SEG_REG_ES, edi, value32); + + if (BX_CPU_THIS_PTR get_DF()) + edi -= 4; + else + edi += 4; + + RDI = edi; +} + +#if BX_SUPPORT_X86_64 + +// 32-bit operand size, 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD64_YdDX(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("INSD64_YdDX: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit64u rdi = RDI; + + // Write a zero to memory, to trigger any segment or page + // faults before reading from IO port. + write_virtual_dword_64(BX_SEG_REG_ES, rdi, 0); + + Bit32u value32 = BX_INP(DX, 4); + + /* no seg override allowed */ + write_virtual_dword_64(BX_SEG_REG_ES, rdi, value32); + + if (BX_CPU_THIS_PTR get_DF()) + rdi -= 4; + else + rdi += 4; + + RDI = rdi; +} + +#endif + // // REP OUTS methods // void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSB_DXXb(bxInstruction_c *i) { - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB_DXXb); -#if BX_SUPPORT_X86_64 - if (i->as32L()) { - BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI - } -#endif -} - -void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSW_DXXw(bxInstruction_c *i) -{ - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW_DXXw); -#if BX_SUPPORT_X86_64 - if (i->as32L()) { - BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI - } -#endif -} - -void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSD_DXXd(bxInstruction_c *i) -{ - BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD_DXXd); -#if BX_SUPPORT_X86_64 - if (i->as32L()) { - BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI - } -#endif -} - -// -// OUTSB/OUTSW/OUTSD methods -// - -void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB_DXXb(bxInstruction_c *i) -{ - if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { - BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !")); - exception(BX_GP_EXCEPTION, 0, 0); - } - - Bit8u value8; - #if BX_SUPPORT_X86_64 if (i->as64L()) { - Bit64u rsi = RSI; - - value8 = read_virtual_byte_64(i->seg(), rsi); - BX_OUTP(DX, value8, 1); - - if (BX_CPU_THIS_PTR get_DF()) - rsi--; - else - rsi++; - - RSI = rsi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB64_DXXb); } else #endif if (i->as32L()) { - Bit32u esi = ESI; - - value8 = read_virtual_byte(i->seg(), esi); - BX_OUTP(DX, value8, 1); - - if (BX_CPU_THIS_PTR get_DF()) - esi--; - else - esi++; - - RSI = esi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB32_DXXb); + BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } - else { // address size 16-bit - Bit16u si = SI; - - value8 = read_virtual_byte_32(i->seg(), si); - BX_OUTP(DX, value8, 1); - - if (BX_CPU_THIS_PTR get_DF()) - si--; - else - si++; - - SI = si; + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB16_DXXb); } } -// output word string to port -void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW_DXXw(bxInstruction_c *i) +// 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB16_DXXb(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("OUTSB16_DXXb: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit16u si = SI; + + Bit8u value8 = read_virtual_byte_32(i->seg(), si); + BX_OUTP(DX, value8, 1); + + if (BX_CPU_THIS_PTR get_DF()) + si--; + else + si++; + + SI = si; +} + +// 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB32_DXXb(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("OUTSB32_DXXb: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit32u esi = ESI; + + Bit8u value8 = read_virtual_byte(i->seg(), esi); + BX_OUTP(DX, value8, 1); + + if (BX_CPU_THIS_PTR get_DF()) + esi--; + else + esi++; + + RSI = esi; +} + +#if BX_SUPPORT_X86_64 + +// 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB64_DXXb(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 1)) { + BX_DEBUG(("OUTSB64_DXXb: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit64u rsi = RSI; + + Bit8u value8 = read_virtual_byte_64(i->seg(), rsi); + BX_OUTP(DX, value8, 1); + + if (BX_CPU_THIS_PTR get_DF()) + rsi--; + else + rsi++; + + RSI = rsi; +} + +#endif + +void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSW_DXXw(bxInstruction_c *i) +{ +#if BX_SUPPORT_X86_64 + if (i->as64L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW64_DXXw); + } + else +#endif + if (i->as32L()) { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW32_DXXw); + BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI + } + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW16_DXXw); + } +} + +// 16-bit operand size, 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW16_DXXw(bxInstruction_c *i) { if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { - BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !")); + BX_DEBUG(("OUTSW16_DXXw: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0, 0); } Bit16u value16; + Bit16u si = SI; + unsigned incr = 2; -#if BX_SUPPORT_X86_64 - if (i->as64L()) { - Bit64u rsi = RSI; - - value16 = read_virtual_word_64(i->seg(), rsi); - BX_OUTP(DX, value16, 2); - - if (BX_CPU_THIS_PTR get_DF()) - rsi -= 2; - else - rsi += 2; - - RSI = rsi; +#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) { + Bit32u wordCount = CX; + wordCount = FastRepOUTSW(i, i->seg(), si, DX, wordCount); + if (wordCount) { + // Decrement eCX. Note, the main loop will decrement 1 also, so + // decrement by one less than expected, like the case above. + BX_TICKN(wordCount-1); // Main cpu loop also decrements one more. + CX -= (wordCount-1); + incr = wordCount << 1; // count * 2. + } + else { + value16 = read_virtual_word_32(i->seg(), si); + BX_OUTP(DX, value16, 2); + } } else #endif { - Bit32u esi; - Bit32u incr = 2; - - if (i->as32L()) - esi = ESI; - else - esi = SI; - -#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) { - Bit32u wordCount; - - if (i->as32L()) - wordCount = ECX; - else - wordCount = CX; - - wordCount = FastRepOUTSW(i, i->seg(), esi, DX, wordCount); - if (wordCount) { - // Decrement eCX. Note, the main loop will decrement 1 also, so - // decrement by one less than expected, like the case above. - BX_TICKN(wordCount-1); // Main cpu loop also decrements one more. - - if (i->as32L()) - RCX = ECX - (wordCount-1); - else - CX -= (wordCount-1); - incr = wordCount << 1; // count * 2. - } - else { - value16 = read_virtual_word(i->seg(), esi); - BX_OUTP(DX, value16, 2); - } - } - else -#endif - { - value16 = read_virtual_word(i->seg(), esi); - BX_OUTP(DX, value16, 2); - } - - if (i->as32L()) { - if (BX_CPU_THIS_PTR get_DF()) - RSI = ESI - incr; - else - RSI = ESI + incr; - } - else { - if (BX_CPU_THIS_PTR get_DF()) - SI = SI - incr; - else - SI = SI + incr; - } + value16 = read_virtual_word_32(i->seg(), si); + BX_OUTP(DX, value16, 2); } + + if (BX_CPU_THIS_PTR get_DF()) + SI = SI - incr; + else + SI = SI + incr; } -// output doubleword string to port -void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD_DXXd(bxInstruction_c *i) +// 16-bit operand size, 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW32_DXXw(bxInstruction_c *i) { - if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { - BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !")); + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("OUTSW32_DXXw: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0, 0); } - Bit32u value32; + Bit16u value16; + Bit32u esi = ESI; + unsigned incr = 2; + +#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) { + Bit32u wordCount = ECX; + wordCount = FastRepOUTSW(i, i->seg(), esi, DX, wordCount); + if (wordCount) { + // Decrement eCX. Note, the main loop will decrement 1 also, so + // decrement by one less than expected, like the case above. + BX_TICKN(wordCount-1); // Main cpu loop also decrements one more. + RCX = ECX - (wordCount-1); + incr = wordCount << 1; // count * 2. + } + else { + value16 = read_virtual_word(i->seg(), esi); + BX_OUTP(DX, value16, 2); + } + } + else +#endif + { + value16 = read_virtual_word(i->seg(), esi); + BX_OUTP(DX, value16, 2); + } + + if (BX_CPU_THIS_PTR get_DF()) + RSI = ESI - incr; + else + RSI = ESI + incr; +} +#if BX_SUPPORT_X86_64 + +// 16-bit operand size, 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW64_DXXw(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 2)) { + BX_DEBUG(("OUTSW64_DXXw: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit64u rsi = RSI; + + Bit16u value16 = read_virtual_word_64(i->seg(), rsi); + BX_OUTP(DX, value16, 2); + + if (BX_CPU_THIS_PTR get_DF()) + rsi -= 2; + else + rsi += 2; + + RSI = rsi; +} + +#endif + +void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSD_DXXd(bxInstruction_c *i) +{ #if BX_SUPPORT_X86_64 if (i->as64L()) { - Bit64u rsi = RSI; - - value32 = read_virtual_dword_64(i->seg(), rsi); - BX_OUTP(DX, value32, 4); - - if (BX_CPU_THIS_PTR get_DF()) - rsi -= 4; - else - rsi += 4; - - RSI = rsi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD64_DXXd); } else #endif if (i->as32L()) { - Bit32u esi = ESI; - - value32 = read_virtual_dword(i->seg(), esi); - BX_OUTP(DX, value32, 4); - - if (BX_CPU_THIS_PTR get_DF()) - esi -= 4; - else - esi += 4; - - RSI = esi; + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD32_DXXd); + BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } - else { // address size 16-bit - Bit16u si = SI; - - value32 = read_virtual_dword_32(i->seg(), si); - BX_OUTP(DX, value32, 4); - - if (BX_CPU_THIS_PTR get_DF()) - si -= 4; - else - si += 4; - - SI = si; + else { + BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD16_DXXd); } } +// 32-bit operand size, 16-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD16_DXXd(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("OUTSD16_DXXd: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit16u si = SI; + + Bit32u value32 = read_virtual_dword_32(i->seg(), si); + BX_OUTP(DX, value32, 4); + + if (BX_CPU_THIS_PTR get_DF()) + si -= 4; + else + si += 4; + + SI = si; +} + +// 32-bit operand size, 32-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD32_DXXd(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("OUTSD32_DXXd: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit32u esi = ESI; + + Bit32u value32 = read_virtual_dword(i->seg(), esi); + BX_OUTP(DX, value32, 4); + + if (BX_CPU_THIS_PTR get_DF()) + esi -= 4; + else + esi += 4; + + RSI = esi; +} + +#if BX_SUPPORT_X86_64 + +// 32-bit operand size, 64-bit address size +void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD64_DXXd(bxInstruction_c *i) +{ + if (! BX_CPU_THIS_PTR allow_io(DX, 4)) { + BX_DEBUG(("OUTSD64_DXXd: I/O access not allowed !")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + Bit64u rsi = RSI; + + Bit32u value32 = read_virtual_dword_64(i->seg(), rsi); + BX_OUTP(DX, value32, 4); + + if (BX_CPU_THIS_PTR get_DF()) + rsi -= 4; + else + rsi += 4; + + RSI = rsi; +} + +#endif + // // non repeatable IN/OUT methods //