2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2004-09-14 00:48:11 +04:00
|
|
|
// $Id: access.cc,v 1.46 2004-09-13 20:48:09 sshwarts Exp $
|
2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2001-04-10 06:20:02 +04:00
|
|
|
// Copyright (C) 2001 MandrakeSoft S.A.
|
2001-04-10 05:04:59 +04:00
|
|
|
//
|
|
|
|
// MandrakeSoft S.A.
|
|
|
|
// 43, rue d'Aboukir
|
|
|
|
// 75002 Paris - France
|
|
|
|
// http://www.linux-mandrake.com/
|
|
|
|
// http://www.mandrakesoft.com/
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
|
|
|
2001-05-24 22:46:34 +04:00
|
|
|
#define NEED_CPU_REG_SHORTCUTS 1
|
2001-04-10 05:04:59 +04:00
|
|
|
#include "bochs.h"
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
#define LOG_THIS BX_CPU_THIS_PTR
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-05-23 12:16:07 +04:00
|
|
|
#if BX_USE_CPU_SMF
|
|
|
|
#define this (BX_CPU(0))
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-24 08:43:59 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
#define IsLongMode() (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
|
|
|
|
#define LPFOf(laddr) ((laddr) & BX_CONST64(0xfffffffffffff000))
|
2003-03-13 03:37:40 +03:00
|
|
|
#define BX_CANONICAL_BITS 48
|
2003-10-24 22:34:16 +04:00
|
|
|
#define IsCanonical(offset) ((Bit64u)((((Bit64s)(offset)) >> (BX_CANONICAL_BITS-1)) + 1) < 2)
|
2003-03-13 03:37:40 +03:00
|
|
|
|
|
|
|
//#define BX_CANONICAL_LO BX_CONST64(0xffff800000000000)
|
|
|
|
//#define BX_CANONICAL_HI BX_CONST64(0x0000800000000000)
|
|
|
|
//#define IsCanonical(offset) ((Bit64u)(offset-BX_CANONICAL_LO) < (Bit64u)(BX_CANONICAL_HI-BX_CANONICAL_LO))
|
|
|
|
|
2002-09-24 08:43:59 +04:00
|
|
|
#else
|
|
|
|
#define IsLongMode() (0)
|
|
|
|
#define LPFOf(laddr) ((laddr) & 0xfffff000)
|
2003-03-13 03:37:40 +03:00
|
|
|
#define IsCanonical(offset) (0)
|
2002-09-24 08:43:59 +04:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::write_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned length)
|
|
|
|
{
|
|
|
|
Bit32u upper_limit;
|
|
|
|
|
2002-09-13 08:33:42 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
2003-03-13 03:37:40 +03:00
|
|
|
// do canonical checks
|
|
|
|
if (!IsCanonical(offset)) {
|
|
|
|
BX_ERROR(("Canonical Address Failure %08x%08x",(Bit32u)(offset >> 32),(Bit32u)(offset & 0xffffffff)));
|
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
}
|
2002-09-24 08:43:59 +04:00
|
|
|
seg->cache.valid |= SegAccessWOK;
|
2002-09-13 08:33:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
if (protected_mode()) {
|
|
|
|
if (seg->cache.valid==0) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_ERROR(("seg = %s", BX_CPU_THIS_PTR strseg(seg)));
|
|
|
|
BX_ERROR(("seg->selector.value = %04x", (unsigned) seg->selector.value));
|
|
|
|
BX_ERROR(("write_virtual_checks: valid bit = 0"));
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_ERROR(("CS: %04x", (unsigned) BX_CPU_THIS_PTR sregs[1].selector.value));
|
|
|
|
BX_ERROR(("IP: %04x", (unsigned) BX_CPU_THIS_PTR prev_eip));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seg->cache.p == 0) { /* not present */
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("write_virtual_checks(): segment not present"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
2003-10-24 22:34:16 +04:00
|
|
|
switch (seg->cache.type) {
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0: case 1: // read only
|
|
|
|
case 4: case 5: // read only, expand down
|
|
|
|
case 8: case 9: // execute only
|
|
|
|
case 10: case 11: // execute/read
|
|
|
|
case 12: case 13: // execute only, conforming
|
|
|
|
case 14: case 15: // execute/read-only, conforming
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("write_virtual_checks(): no write access to seg"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 2: case 3: /* read/write */
|
2002-09-13 08:33:42 +04:00
|
|
|
|
|
|
|
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
|
|
|
|| (length-1 > seg->cache.u.segment.limit_scaled)) {
|
|
|
|
BX_INFO(("write_virtual_checks(): write beyond limit, r/w"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
if (seg->cache.u.segment.limit_scaled >= 7) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
// Mark cache as being OK type for succeeding writes. The limit
|
|
|
|
// checks still needs to be done though, but is more simple. We
|
|
|
|
// could probably also optimize that out with a flag for the case
|
|
|
|
// when limit is the maximum 32bit value. Limit should accomodate
|
|
|
|
// at least a dword, since we subtract from it in the simple
|
|
|
|
// limit check in other functions, and we don't want the value to roll.
|
|
|
|
// Only normal segments (not expand down) are handled this way.
|
|
|
|
seg->cache.valid |= SegAccessWOK;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 6: case 7: /* read write, expand down */
|
|
|
|
if (seg->cache.u.segment.d_b)
|
|
|
|
upper_limit = 0xffffffff;
|
|
|
|
else
|
|
|
|
upper_limit = 0x0000ffff;
|
2003-10-24 22:34:16 +04:00
|
|
|
if ((offset <= seg->cache.u.segment.limit_scaled) ||
|
2001-04-10 05:04:59 +04:00
|
|
|
(offset > upper_limit) ||
|
2003-10-24 22:34:16 +04:00
|
|
|
((upper_limit - offset) < (length - 1))) {
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("write_virtual_checks(): write beyond limit, r/w ED"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
else { /* real mode */
|
2002-09-13 08:33:42 +04:00
|
|
|
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
|
|
|
|| (length-1 > seg->cache.u.segment.limit_scaled)) {
|
2001-05-30 22:56:02 +04:00
|
|
|
//BX_INFO(("write_virtual_checks() SEG EXCEPTION: %x:%x + %x",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
// (unsigned) seg->selector.value, (unsigned) offset, (unsigned) length));
|
2001-04-10 05:04:59 +04:00
|
|
|
if (seg == & BX_CPU_THIS_PTR sregs[2]) exception(BX_SS_EXCEPTION, 0, 0);
|
|
|
|
else exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
if (seg->cache.u.segment.limit_scaled >= 7) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
// Mark cache as being OK type for succeeding writes. See notes above.
|
|
|
|
seg->cache.valid |= SegAccessWOK;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_virtual_checks(bx_segment_reg_t *seg, bx_address offset,
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned length)
|
|
|
|
{
|
|
|
|
Bit32u upper_limit;
|
|
|
|
|
2002-09-13 08:33:42 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
2003-03-13 03:37:40 +03:00
|
|
|
// do canonical checks
|
|
|
|
if (!IsCanonical(offset)) {
|
|
|
|
BX_ERROR(("Canonical Address Failure %08x%08x",(Bit32u)(offset >> 32),(Bit32u)(offset & 0xffffffff)));
|
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
}
|
2002-09-24 08:43:59 +04:00
|
|
|
seg->cache.valid |= SegAccessROK;
|
2002-09-13 08:33:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
if (protected_mode()) {
|
|
|
|
if (seg->cache.valid==0) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_ERROR(("seg = %s", BX_CPU_THIS_PTR strseg(seg)));
|
|
|
|
BX_ERROR(("seg->selector.value = %04x", (unsigned) seg->selector.value));
|
|
|
|
//BX_ERROR(("read_virtual_checks: valid bit = 0"));
|
|
|
|
//BX_ERROR(("CS: %04x", (unsigned)
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
// BX_CPU_THIS_PTR sregs[1].selector.value));
|
2001-05-30 22:56:02 +04:00
|
|
|
//BX_ERROR(("IP: %04x", (unsigned) BX_CPU_THIS_PTR prev_eip));
|
2002-09-13 04:15:23 +04:00
|
|
|
//debug(EIP);
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seg->cache.p == 0) { /* not present */
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("read_virtual_checks(): segment not present"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
switch (seg->cache.type) {
|
2001-04-10 05:04:59 +04:00
|
|
|
case 0: case 1: /* read only */
|
|
|
|
case 10: case 11: /* execute/read */
|
|
|
|
case 14: case 15: /* execute/read-only, conforming */
|
2002-09-13 08:33:42 +04:00
|
|
|
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
|
|
|
|| (length-1 > seg->cache.u.segment.limit_scaled)) {
|
|
|
|
BX_INFO(("read_virtual_checks(): write beyond limit"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
if (seg->cache.u.segment.limit_scaled >= 7) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
// Mark cache as being OK type for succeeding writes. See notes for
|
|
|
|
// write checks; similar code.
|
|
|
|
seg->cache.valid |= SegAccessROK;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: case 3: /* read/write */
|
2002-09-13 08:33:42 +04:00
|
|
|
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
|
|
|
|| (length-1 > seg->cache.u.segment.limit_scaled)) {
|
|
|
|
BX_INFO(("read_virtual_checks(): write beyond limit"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
if (seg->cache.u.segment.limit_scaled >= 7) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
// Mark cache as being OK type for succeeding writes. See notes for
|
|
|
|
// write checks; similar code.
|
|
|
|
seg->cache.valid |= SegAccessROK;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4: case 5: /* read only, expand down */
|
|
|
|
if (seg->cache.u.segment.d_b)
|
|
|
|
upper_limit = 0xffffffff;
|
|
|
|
else
|
|
|
|
upper_limit = 0x0000ffff;
|
2003-10-24 22:34:16 +04:00
|
|
|
if ((offset <= seg->cache.u.segment.limit_scaled) ||
|
2001-04-10 05:04:59 +04:00
|
|
|
(offset > upper_limit) ||
|
2003-10-24 22:34:16 +04:00
|
|
|
((upper_limit - offset) < (length - 1))) {
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("read_virtual_checks(): write beyond limit"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6: case 7: /* read write, expand down */
|
|
|
|
if (seg->cache.u.segment.d_b)
|
|
|
|
upper_limit = 0xffffffff;
|
|
|
|
else
|
|
|
|
upper_limit = 0x0000ffff;
|
2003-10-24 22:34:16 +04:00
|
|
|
if ((offset <= seg->cache.u.segment.limit_scaled) ||
|
2001-04-10 05:04:59 +04:00
|
|
|
(offset > upper_limit) ||
|
2003-10-24 22:34:16 +04:00
|
|
|
((upper_limit - offset) < (length - 1))) {
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("read_virtual_checks(): write beyond limit"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8: case 9: /* execute only */
|
|
|
|
case 12: case 13: /* execute only, conforming */
|
|
|
|
/* can't read or write an execute-only segment */
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_INFO(("read_virtual_checks(): execute only"));
|
2001-04-10 05:04:59 +04:00
|
|
|
exception(int_number(seg), 0, 0);
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
else { /* real mode */
|
2002-09-13 08:33:42 +04:00
|
|
|
if (offset > (seg->cache.u.segment.limit_scaled - length + 1)
|
|
|
|
|| (length-1 > seg->cache.u.segment.limit_scaled)) {
|
2001-05-30 22:56:02 +04:00
|
|
|
//BX_ERROR(("read_virtual_checks() SEG EXCEPTION: %x:%x + %x",
|
2001-05-25 22:44:38 +04:00
|
|
|
// (unsigned) seg->selector.value, (unsigned) offset, (unsigned) length));
|
2001-04-10 05:04:59 +04:00
|
|
|
if (seg == & BX_CPU_THIS_PTR sregs[2]) exception(BX_SS_EXCEPTION, 0, 0);
|
|
|
|
else exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
if (seg->cache.u.segment.limit_scaled >= 7) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
// Mark cache as being OK type for succeeding writes. See notes for
|
|
|
|
// write checks; similar code.
|
|
|
|
seg->cache.valid |= SegAccessROK;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
char * BX_CPP_AttrRegparmN(1)
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_CPU_C::strseg(bx_segment_reg_t *seg)
|
|
|
|
{
|
|
|
|
if (seg == &BX_CPU_THIS_PTR sregs[0]) return("ES");
|
|
|
|
else if (seg == & BX_CPU_THIS_PTR sregs[1]) return("CS");
|
|
|
|
else if (seg == & BX_CPU_THIS_PTR sregs[2]) return("SS");
|
|
|
|
else if (seg == &BX_CPU_THIS_PTR sregs[3]) return("DS");
|
|
|
|
else if (seg == &BX_CPU_THIS_PTR sregs[4]) return("FS");
|
|
|
|
else if (seg == &BX_CPU_THIS_PTR sregs[5]) return("GS");
|
|
|
|
else {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_ERROR(("undefined segment passed to strseg()!"));
|
2001-04-10 05:04:59 +04:00
|
|
|
return("??");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::write_virtual_byte(unsigned s, bx_address offset, Bit8u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= seg->cache.u.segment.limit_scaled)) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 1, BX_WRITE);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
2003-10-24 22:34:16 +04:00
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
2004-09-14 00:48:11 +04:00
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
|
|
|
Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
|
|
|
|
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
*hostAddr = *data;
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
access_linear(laddr, 1, pl, BX_WRITE, (void *) data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_virtual_checks(seg, offset, 1);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::write_virtual_word(unsigned s, bx_address offset, Bit16u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < seg->cache.u.segment.limit_scaled)) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 2, BX_WRITE);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffe) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-05 08:56:11 +04:00
|
|
|
WriteHostWordToLittleEndian(hostAddr, *data);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
access_linear(laddr, 2, pl, BX_WRITE, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_virtual_checks(seg, offset, 2);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::write_virtual_dword(unsigned s, bx_address offset, Bit32u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < (seg->cache.u.segment.limit_scaled-2))) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 4, BX_WRITE);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffc) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
|
|
|
|
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-05 08:56:11 +04:00
|
|
|
WriteHostDWordToLittleEndian(hostAddr, *data);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
access_linear(laddr, 4, pl, BX_WRITE, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_virtual_checks(seg, offset, 4);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_virtual_byte(unsigned s, bx_address offset, Bit8u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessROK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= seg->cache.u.segment.limit_scaled)) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 1, BX_READ);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
2002-09-06 23:21:55 +04:00
|
|
|
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us read access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1<<pl)) { // Read this pl OK.
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
|
|
|
Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (hostPageAddr) {
|
|
|
|
*data = *hostAddr;
|
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
access_linear(laddr, 1, pl, BX_READ, (void *) data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_virtual_checks(seg, offset, 1);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_virtual_word(unsigned s, bx_address offset, Bit16u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessROK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < seg->cache.u.segment.limit_scaled)) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 2, BX_READ);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffe) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
2002-09-06 23:21:55 +04:00
|
|
|
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us read access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1<<pl)) { // Read this pl OK.
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (hostPageAddr) {
|
2002-09-05 08:56:11 +04:00
|
|
|
ReadHostWordFromLittleEndian(hostAddr, *data);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
access_linear(laddr, 2, pl, BX_READ, (void *) data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_virtual_checks(seg, offset, 2);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_virtual_dword(unsigned s, bx_address offset, Bit32u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessROK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < (seg->cache.u.segment.limit_scaled-2))) {
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 4, BX_READ);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffc) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
2002-09-06 23:21:55 +04:00
|
|
|
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us read access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1<<pl)) { // Read this pl OK.
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (hostPageAddr) {
|
2002-09-05 08:56:11 +04:00
|
|
|
ReadHostDWordFromLittleEndian(hostAddr, *data);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
access_linear(laddr, 4, pl, BX_READ, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_virtual_checks(seg, offset, 4);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// special Read-Modify-Write operations //
|
|
|
|
// address translation info is kept across read/write calls //
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_RMW_virtual_byte(unsigned s, bx_address offset, Bit8u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= seg->cache.u.segment.limit_scaled)) {
|
2002-09-03 08:54:28 +04:00
|
|
|
unsigned pl;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-28 23:51:08 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 1, BX_RW);
|
2002-09-03 08:54:28 +04:00
|
|
|
pl = (CPL==3);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
|
|
|
Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
*data = *hostAddr;
|
2003-02-28 05:37:18 +03:00
|
|
|
BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr;
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
2002-09-03 08:54:28 +04:00
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
|
|
|
}
|
2002-09-03 08:54:28 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Accelerated attempt falls through to long path. Do it the
|
|
|
|
// old fashioned way...
|
|
|
|
access_linear(laddr, 1, pl, BX_RW, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
write_virtual_checks(seg, offset, 1);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_RMW_virtual_word(unsigned s, bx_address offset, Bit16u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < seg->cache.u.segment.limit_scaled)) {
|
2002-09-03 08:54:28 +04:00
|
|
|
unsigned pl;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-28 23:51:08 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 2, BX_RW);
|
2002-09-03 08:54:28 +04:00
|
|
|
pl = (CPL==3);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffe) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-05 08:56:11 +04:00
|
|
|
ReadHostWordFromLittleEndian(hostAddr, *data);
|
2003-02-28 05:37:18 +03:00
|
|
|
BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr;
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
2002-09-03 08:54:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
|
|
|
}
|
2002-09-03 08:54:28 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
access_linear(laddr, 2, pl, BX_RW, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
write_virtual_checks(seg, offset, 2);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_RMW_virtual_dword(unsigned s, bx_address offset, Bit32u *data)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2001-04-10 05:04:59 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset < (seg->cache.u.segment.limit_scaled-2))) {
|
2002-09-03 08:54:28 +04:00
|
|
|
unsigned pl;
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-28 23:51:08 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 4, BX_RW);
|
2002-09-03 08:54:28 +04:00
|
|
|
pl = (CPL==3);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-09-03 08:54:28 +04:00
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xffc) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-05 08:56:11 +04:00
|
|
|
ReadHostDWordFromLittleEndian(hostAddr, *data);
|
2003-02-28 05:37:18 +03:00
|
|
|
BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr;
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
2002-09-03 08:54:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
|
|
|
}
|
2002-09-03 08:54:28 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
access_linear(laddr, 4, pl, BX_RW, (void *) data);
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
return;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
Integrated patches for:
- Paging code rehash. You must now use --enable-4meg-pages to
use 4Meg pages, with the default of disabled, since we don't well
support 4Meg pages yet. Paging table walks model a real CPU
more closely now, and I fixed some bugs in the old logic.
- Segment check redundancy elimination. After a segment is loaded,
reads and writes are marked when a segment type check succeeds, and
they are skipped thereafter, when possible.
- Repeated IO and memory string copy acceleration. Only some variants
of instructions are available on all platforms, word and dword
variants only on x86 for the moment due to alignment and endian issues.
This is compiled in currently with no option - I should add a configure
option.
- Added a guest linear address to host TLB. Actually, I just stick
the host address (mem.vector[addr] address) in the upper 29 bits
of the field 'combined_access' since they are unused. Convenient
for now. I'm only storing page frame addresses. This was the
simplest for of such a TLB. We can likely enhance this. Also,
I only accelerated the normal read/write routines in access.cc.
Could also modify the read-modify-write versions too. You must
use --enable-guest2host-tlb, to try this out. Currently speeds
up Win95 boot time by about 3.5% for me. More ground to cover...
- Minor mods to CPUI/MOV_CdRd for CMOV.
- Integrated enhancements from Volker to getHostMemAddr() for PCI
being enabled.
2002-09-02 00:12:09 +04:00
|
|
|
write_virtual_checks(seg, offset, 4);
|
|
|
|
goto accessOK;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1)
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_CPU_C::write_RMW_virtual_byte(Bit8u val8)
|
|
|
|
{
|
2002-09-07 01:54:58 +04:00
|
|
|
if (BX_CPU_THIS_PTR address_xlation.pages > 2) {
|
|
|
|
// Pages > 2 means it stores a host address for direct access.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit8u *hostAddr = (Bit8u *) BX_CPU_THIS_PTR address_xlation.pages;
|
|
|
|
*hostAddr = val8;
|
2002-09-07 01:54:58 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// address_xlation.pages must be 1
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 1, &val8);
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1)
|
2001-04-10 05:04:59 +04:00
|
|
|
BX_CPU_C::write_RMW_virtual_word(Bit16u val16)
|
|
|
|
{
|
2002-09-07 01:54:58 +04:00
|
|
|
if (BX_CPU_THIS_PTR address_xlation.pages > 2) {
|
|
|
|
// Pages > 2 means it stores a host address for direct access.
|
|
|
|
Bit16u *hostAddr = (Bit16u *) BX_CPU_THIS_PTR address_xlation.pages;
|
|
|
|
WriteHostWordToLittleEndian(hostAddr, val16);
|
|
|
|
}
|
|
|
|
else if (BX_CPU_THIS_PTR address_xlation.pages == 1) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 2, &val16);
|
|
|
|
}
|
|
|
|
else {
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 1, &val16);
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2, 1, ((Bit8u *) &val16) + 1);
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 1, ((Bit8u *) &val16) + 1);
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2, 1, &val16);
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BX_CPU_C::write_RMW_virtual_dword(Bit32u val32)
|
|
|
|
{
|
2002-09-07 01:54:58 +04:00
|
|
|
if (BX_CPU_THIS_PTR address_xlation.pages > 2) {
|
|
|
|
// Pages > 2 means it stores a host address for direct access.
|
|
|
|
Bit32u *hostAddr = (Bit32u *) BX_CPU_THIS_PTR address_xlation.pages;
|
|
|
|
WriteHostDWordToLittleEndian(hostAddr, val32);
|
|
|
|
}
|
|
|
|
else if (BX_CPU_THIS_PTR address_xlation.pages == 1) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 4, &val32);
|
|
|
|
}
|
|
|
|
else {
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len1,
|
|
|
|
&val32);
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len2,
|
|
|
|
((Bit8u *) &val32) + BX_CPU_THIS_PTR address_xlation.len1);
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len1,
|
|
|
|
((Bit8u *) &val32) + (4 - BX_CPU_THIS_PTR address_xlation.len1));
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len2,
|
|
|
|
&val32);
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::write_virtual_qword(unsigned s, bx_address offset, Bit64u *data)
|
2002-09-05 00:23:54 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2002-09-05 00:23:54 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= (seg->cache.u.segment.limit_scaled-7))) {
|
2002-09-05 00:23:54 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 8, BX_WRITE);
|
2002-09-05 00:23:54 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xff8) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-05 08:56:11 +04:00
|
|
|
WriteHostQWordToLittleEndian(hostAddr, *data);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
2002-09-05 00:23:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
access_linear(laddr, 8, pl, BX_WRITE, (void *) data);
|
2002-09-05 00:23:54 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_virtual_checks(seg, offset, 8);
|
|
|
|
goto accessOK;
|
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_virtual_qword(unsigned s, bx_address offset, Bit64u *data)
|
2002-09-05 00:23:54 +04:00
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
bx_address laddr;
|
2002-09-05 00:23:54 +04:00
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
|
|
|
if (seg->cache.valid & SegAccessROK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= (seg->cache.u.segment.limit_scaled-7))) {
|
2002-09-05 00:23:54 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-13 18:04:11 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 8, BX_READ);
|
2002-09-05 00:23:54 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (pageOffset <= 0xff8) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
2002-09-06 23:21:55 +04:00
|
|
|
if (BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)) {
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
// See if the TLB entry privilege level allows us read access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1<<pl)) { // Read this pl OK.
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
if (hostPageAddr) {
|
2002-09-05 08:56:11 +04:00
|
|
|
ReadHostQWordFromLittleEndian(hostAddr, *data);
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
return;
|
2002-09-05 00:23:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
}
|
2002-09-05 00:23:54 +04:00
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
Now, when you compile with --enable-guest2host-tlb, non-paged
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
2002-09-05 06:31:24 +04:00
|
|
|
access_linear(laddr, 8, pl, BX_READ, (void *) data);
|
2002-09-05 00:23:54 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_virtual_checks(seg, offset, 8);
|
|
|
|
goto accessOK;
|
|
|
|
}
|
2002-09-13 08:33:42 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
BX_CPU_C::write_RMW_virtual_qword(Bit64u val64)
|
|
|
|
{
|
|
|
|
if (BX_CPU_THIS_PTR address_xlation.pages > 2) {
|
|
|
|
// Pages > 2 means it stores a host address for direct access.
|
|
|
|
Bit64u *hostAddr = (Bit64u *) BX_CPU_THIS_PTR address_xlation.pages;
|
|
|
|
WriteHostQWordToLittleEndian(hostAddr, val64);
|
|
|
|
}
|
|
|
|
else if (BX_CPU_THIS_PTR address_xlation.pages == 1) {
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1, 8, &val64);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len1,
|
|
|
|
&val64);
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len2,
|
|
|
|
((Bit8u *) &val64) + BX_CPU_THIS_PTR address_xlation.len1);
|
|
|
|
#else
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress1,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len1,
|
|
|
|
((Bit8u *) &val64) + (8 - BX_CPU_THIS_PTR address_xlation.len1));
|
|
|
|
BX_CPU_THIS_PTR mem->writePhysicalPage(this,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.paddress2,
|
|
|
|
BX_CPU_THIS_PTR address_xlation.len2,
|
|
|
|
&val64);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-03 02:59:12 +03:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2002-09-13 08:33:42 +04:00
|
|
|
BX_CPU_C::read_RMW_virtual_qword(unsigned s, bx_address offset, Bit64u *data)
|
|
|
|
{
|
|
|
|
bx_address laddr;
|
|
|
|
bx_segment_reg_t *seg;
|
|
|
|
|
|
|
|
seg = &BX_CPU_THIS_PTR sregs[s];
|
|
|
|
if (seg->cache.valid & SegAccessWOK) {
|
2003-03-13 03:37:40 +03:00
|
|
|
if ((IsLongMode() && IsCanonical(offset))
|
2003-10-24 22:34:16 +04:00
|
|
|
|| (offset <= (seg->cache.u.segment.limit_scaled-7))) {
|
2002-09-13 08:33:42 +04:00
|
|
|
unsigned pl;
|
|
|
|
accessOK:
|
|
|
|
laddr = seg->cache.u.segment.base + offset;
|
2003-02-28 23:51:08 +03:00
|
|
|
BX_INSTR_MEM_DATA(BX_CPU_ID, laddr, 8, BX_RW);
|
2002-09-13 08:33:42 +04:00
|
|
|
pl = (CPL==3);
|
|
|
|
|
|
|
|
#if BX_SupportGuest2HostTLB
|
|
|
|
{
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u pageOffset = laddr & 0xfff;
|
2002-09-13 08:33:42 +04:00
|
|
|
if (pageOffset <= 0xff8) { // Make sure access does not span 2 pages.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u tlbIndex = BX_TLB_INDEX_OF(laddr);
|
|
|
|
bx_address lpf = LPFOf(laddr);
|
|
|
|
if ((BX_CPU_THIS_PTR TLB.entry[tlbIndex].lpf == BX_TLB_LPF_VALUE(lpf)))
|
|
|
|
{
|
2002-09-13 08:33:42 +04:00
|
|
|
// See if the TLB entry privilege level allows us write access
|
|
|
|
// from this CPL.
|
2004-09-14 00:48:11 +04:00
|
|
|
Bit32u accessBits = BX_CPU_THIS_PTR TLB.entry[tlbIndex].accessBits;
|
2003-10-24 22:34:16 +04:00
|
|
|
if (accessBits & (1 << (2 | pl))) {
|
2004-09-14 00:48:11 +04:00
|
|
|
bx_hostpageaddr_t hostPageAddr;
|
|
|
|
hostPageAddr = BX_CPU_THIS_PTR TLB.entry[tlbIndex].hostPageAddr;
|
|
|
|
Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset);
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
Bit32u *pageStamp;
|
|
|
|
pageStamp = & BX_CPU_THIS_PTR iCache.pageWriteStampTable[
|
|
|
|
BX_CPU_THIS_PTR TLB.entry[tlbIndex].ppf>>12];
|
|
|
|
#endif
|
2002-09-13 08:33:42 +04:00
|
|
|
// Current write access has privilege.
|
2002-09-23 01:47:57 +04:00
|
|
|
if (hostPageAddr
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-23 01:47:57 +04:00
|
|
|
&& (*pageStamp & ICacheWriteStampMask)
|
|
|
|
#endif
|
2003-10-24 22:34:16 +04:00
|
|
|
) {
|
2002-09-13 08:33:42 +04:00
|
|
|
ReadHostQWordFromLittleEndian(hostAddr, *data);
|
2003-02-28 05:37:18 +03:00
|
|
|
BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr;
|
2004-07-30 00:15:19 +04:00
|
|
|
#if BX_SUPPORT_ICACHE
|
2002-09-19 23:17:20 +04:00
|
|
|
(*pageStamp)--;
|
|
|
|
#endif
|
2002-09-13 08:33:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // BX_SupportGuest2HostTLB
|
|
|
|
|
|
|
|
access_linear(laddr, 8, pl, BX_RW, (void *) data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_virtual_checks(seg, offset, 8);
|
|
|
|
goto accessOK;
|
|
|
|
}
|
2002-10-11 05:11:11 +04:00
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
//
|
2002-10-11 20:18:00 +04:00
|
|
|
// Some macro defs to make things cleaner for endian-ness issues.
|
|
|
|
// The following routines access a double qword, ie 16-bytes.
|
|
|
|
// For the moment, I redirect these to use the single qword routines
|
|
|
|
// by splitting one access into two.
|
|
|
|
//
|
|
|
|
// Endian Host byte order Guest (x86) byte order
|
|
|
|
// ======================================================
|
|
|
|
// Little 0..7 8..15 0..7 8..15
|
|
|
|
// Big 15..8 7...0 0..7 8..15
|
|
|
|
//
|
|
|
|
// Below are the host memory offsets to each of 2 single quadwords, which
|
|
|
|
// are different across big an little endian machines. The memory
|
|
|
|
// accessing routines take care of the access endian issues when accessing
|
|
|
|
// the physical memory image.
|
2003-10-24 22:34:16 +04:00
|
|
|
//
|
|
|
|
|
2002-10-11 20:18:00 +04:00
|
|
|
|
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
|
|
# define Host1stDWordOffset 0
|
|
|
|
# define Host2ndDWordOffset 8
|
|
|
|
#else
|
|
|
|
# define Host1stDWordOffset 8
|
|
|
|
# define Host2ndDWordOffset 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2003-10-25 00:06:12 +04:00
|
|
|
BX_CPU_C::read_virtual_dqword(unsigned s, bx_address offset, Bit8u *data)
|
2002-10-11 05:11:11 +04:00
|
|
|
{
|
2002-10-11 17:55:26 +04:00
|
|
|
// Read Double Quadword.
|
|
|
|
Bit64u *qwords = (Bit64u*) data;
|
|
|
|
|
2002-10-11 20:18:00 +04:00
|
|
|
read_virtual_qword(s, offset+Host1stDWordOffset, &qwords[0]);
|
|
|
|
read_virtual_qword(s, offset+Host2ndDWordOffset, &qwords[1]);
|
2002-10-11 05:11:11 +04:00
|
|
|
}
|
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2003-10-25 00:06:12 +04:00
|
|
|
BX_CPU_C::read_virtual_dqword_aligned(unsigned s, bx_address offset, Bit8u *data)
|
2002-10-11 05:11:11 +04:00
|
|
|
{
|
2002-10-11 17:55:26 +04:00
|
|
|
// If double quadword access is unaligned, #GP(0).
|
2003-10-24 22:34:16 +04:00
|
|
|
if (offset & 0xf) {
|
2002-10-11 17:55:26 +04:00
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
2003-10-24 22:34:16 +04:00
|
|
|
}
|
2002-10-11 17:55:26 +04:00
|
|
|
|
2003-10-25 00:06:12 +04:00
|
|
|
read_virtual_dqword(s, offset, data);
|
2002-10-11 05:11:11 +04:00
|
|
|
}
|
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2003-10-25 00:06:12 +04:00
|
|
|
BX_CPU_C::write_virtual_dqword(unsigned s, bx_address offset, Bit8u *data)
|
2002-10-11 05:11:11 +04:00
|
|
|
{
|
2002-10-11 17:55:26 +04:00
|
|
|
// Write Double Quadword.
|
|
|
|
Bit64u *qwords = (Bit64u*) data;
|
|
|
|
|
2002-10-11 20:18:00 +04:00
|
|
|
write_virtual_qword(s, offset+Host1stDWordOffset, &qwords[0]);
|
|
|
|
write_virtual_qword(s, offset+Host2ndDWordOffset, &qwords[1]);
|
2002-10-11 05:11:11 +04:00
|
|
|
}
|
|
|
|
|
2003-10-24 22:34:16 +04:00
|
|
|
void BX_CPP_AttrRegparmN(3)
|
2003-10-25 00:06:12 +04:00
|
|
|
BX_CPU_C::write_virtual_dqword_aligned(unsigned s, bx_address offset, Bit8u *data)
|
2002-10-11 05:11:11 +04:00
|
|
|
{
|
2002-10-11 17:55:26 +04:00
|
|
|
// If double quadword access is unaligned, #GP(0).
|
2003-10-24 22:34:16 +04:00
|
|
|
if (offset & 0xf) {
|
2002-10-11 17:55:26 +04:00
|
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
2003-10-24 22:34:16 +04:00
|
|
|
}
|
2002-10-11 17:55:26 +04:00
|
|
|
|
2003-10-25 00:06:12 +04:00
|
|
|
write_virtual_dqword(s, offset, data);
|
2002-10-11 05:11:11 +04:00
|
|
|
}
|
2004-06-18 18:11:11 +04:00
|
|
|
|
|
|
|
#if BX_SUPPORT_FPU
|
|
|
|
|
|
|
|
void BX_CPP_AttrRegparmN(3)
|
|
|
|
BX_CPU_C::read_virtual_tword(unsigned s, bx_address offset, floatx80 *data)
|
|
|
|
{
|
|
|
|
// read floating point register
|
|
|
|
read_virtual_qword(s, offset+0, &data->fraction);
|
|
|
|
read_virtual_word (s, offset+8, &data->exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BX_CPP_AttrRegparmN(3)
|
|
|
|
BX_CPU_C::write_virtual_tword(unsigned s, bx_address offset, floatx80 *data)
|
|
|
|
{
|
|
|
|
// store floating point register
|
|
|
|
write_virtual_qword(s, offset+0, &data->fraction);
|
|
|
|
write_virtual_word (s, offset+8, &data->exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|