From 6d51ca08f16ba519a7829c9d6d0157392ae5de23 Mon Sep 17 00:00:00 2001 From: Kevin Lawton Date: Mon, 23 Sep 2002 19:29:15 +0000 Subject: [PATCH] Removed my patches, which are already integrated into bochs. --- bochs/patches/patch.optimize-rep | 1023 ------------------------------ bochs/patches/patch.seg-checks | 438 ------------- 2 files changed, 1461 deletions(-) delete mode 100644 bochs/patches/patch.optimize-rep delete mode 100644 bochs/patches/patch.seg-checks diff --git a/bochs/patches/patch.optimize-rep b/bochs/patches/patch.optimize-rep deleted file mode 100644 index e24c68556..000000000 --- a/bochs/patches/patch.optimize-rep +++ /dev/null @@ -1,1023 +0,0 @@ ----------------------------------------------------------------------- -Patch name: patch.optimize-rep -Author: Kevin Lawton -Date: 2002-08-29 - -Detailed description: - -I made some more performance enhancements, this time -accelerating repeated IO instructions (to get some -better transfers out of the disk access mostly), -and repeated string moves and stores (for memcpy() -and memset() type operations). Enhanced some -variants of: INSW, OUTSW, MOVSB, MOVSW, STOSB. - -These diffs rely slightly on the previous segment -type access check redundancy elimination diffs I -set a couple days ago, so you need those first. -[ YOU MUST USE patch.seg-checks TOO OR THIS WON'T EVEN COMPILE. -bbd] - --Kevin - -Notes: - -- Increase was something like 7% of a win95 boot time. -Previous diffs were an additional 3% of win95 boot -time. -10% total so far, but hey, who's counting? :^) -- Some of the accelerations are bracked with #if __x86__, -because of alignment and endian issues. The byte -oriented variations don't care of course. Could extend -them. -- On x86, could extend the copies even more by using -a native REP instruction since it knows about the -direction flag (eflags.DF). -- Keep in mind, overlapping buffers if you try to extend -things further, and any semantical differences those -imply for move sizes different than the instruction -requests. -- I moved one of the ticks fields in pc_system.h to -the public -area, since I needed to read it. - - - -Patch was created with: - cvs diff -u -Apply patch to what version: - current cvs WITH patch.seg-checks applied -Instructions: - To patch, go to main bochs directory. - Type "patch -p0 < THIS_PATCH_FILE". ----------------------------------------------------------------------- -Index: pc_system.h -=================================================================== -RCS file: /cvsroot/bochs/bochs/pc_system.h,v -retrieving revision 1.11 -diff -u -r1.11 pc_system.h ---- pc_system.h 16 Jun 2002 15:02:27 -0000 1.11 -+++ pc_system.h 29 Aug 2002 16:20:27 -0000 -@@ -59,7 +59,6 @@ - } timer[BX_MAX_TIMERS]; - unsigned num_timers; - Bit64u num_cpu_ticks_in_period; -- Bit64u num_cpu_ticks_left; - void expire_ticks(void); - - #if !defined(PROVIDE_M_IPS) -@@ -67,6 +66,7 @@ - #endif - - public: -+ Bit64u num_cpu_ticks_left; - - Boolean HRQ; // Hold Request - //Boolean INTR; // Interrupt -Index: cpu/io.cc -=================================================================== -RCS file: /cvsroot/bochs/bochs/cpu/io.cc,v -retrieving revision 1.5 -diff -u -r1.5 io.cc ---- cpu/io.cc 3 Oct 2001 13:10:37 -0000 1.5 -+++ cpu/io.cc 29 Aug 2002 16:20:35 -0000 -@@ -36,8 +36,6 @@ - - - -- -- - void - BX_CPU_C::INSB_YbDX(BxInstruction_t *i) - { -@@ -125,6 +123,104 @@ - } - } - -+#if (BX_DEBUGGER == 0) -+#if (defined(__i386__) && __i386__) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u wordCount; -+ bx_segment_reg_t *dstSegPtr; -+ -+ if (i->as_32) -+ wordCount = ECX; -+ else -+ wordCount = CX; -+ dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SREG_ES]; -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ write_virtual_checks(dstSegPtr, edi, 2); -+ if (wordCount) { -+ Bit32u laddr, paddr, wordsCanFit; -+ Bit8u *hostAddrDst; -+ -+ laddr = dstSegPtr->cache.u.segment.base + edi; -+ if (BX_CPU_THIS_PTR cr0.pg) -+ paddr = dtranslate_linear(laddr, CPL==3, BX_WRITE); -+ else -+ paddr = laddr; -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddr = A20ADDR(paddr); -+ -+ hostAddrDst = BX_CPU_THIS_PTR mem->getHostMemAddr(paddr, BX_WRITE); -+ -+ // Check that native host access was not vetoed for that page, and -+ // that the address is word aligned. -+ if ( hostAddrDst && ! (paddr & 1) ) { -+ // See how many words can fit in the rest of this page. -+ wordsCanFit = (0x1000 - (paddr & 0xfff)) >> 1; -+ // Restrict word count to the number that will fit in this page. -+ if (wordCount > wordsCanFit) -+ wordCount = wordsCanFit; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (wordCount) { -+ unsigned transferLen; -+ Bit32u roomDst; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = wordCount<<1; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(dstSegPtr->cache.valid & SegAccessWOK) ) { -+ goto noAcceleration; -+ } -+ roomDst = (dstSegPtr->cache.u.segment.limit_scaled - edi) + 1; -+ if ( roomDst < transferLen ) { -+ goto noAcceleration; -+ } -+ -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -2; -+ else -+ pointerDelta = 2; -+ for (j=0; jas_32) -+ ECX -= (wordCount-1); -+ else -+ CX -= (wordCount-1); -+ incr = wordCount << 1; // count * 2. -+ goto doIncr; -+ } -+ } -+ } -+ } -+#endif // __i386__ -+#endif -+ -+noAcceleration: -+ - // Write a zero to memory, to trigger any segment or page - // faults before reading from IO port. - write_virtual_word(BX_SEG_REG_ES, edi, &value16); -@@ -136,6 +232,10 @@ - incr = 2; - } - -+#if (BX_DEBUGGER == 0) -+doIncr: -+#endif -+ - if (i->as_32) { - if (BX_CPU_THIS_PTR eflags.df) - EDI = EDI - incr; -@@ -236,11 +336,113 @@ - } - } - -+#if (BX_DEBUGGER == 0) -+#if (defined(__i386__) && __i386__) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u wordCount; -+ bx_segment_reg_t *srcSegPtr; -+ -+ if (i->as_32) -+ wordCount = ECX; -+ else -+ wordCount = CX; -+ srcSegPtr = &BX_CPU_THIS_PTR sregs[seg]; -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ read_virtual_checks(srcSegPtr, esi, 2); -+ if (wordCount) { -+ Bit32u laddr, paddr, wordsCanFit; -+ Bit8u *hostAddrSrc; -+ -+ laddr = srcSegPtr->cache.u.segment.base + esi; -+ if (BX_CPU_THIS_PTR cr0.pg) -+ paddr = dtranslate_linear(laddr, CPL==3, BX_READ); -+ else -+ paddr = laddr; -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddr = A20ADDR(paddr); -+ -+ hostAddrSrc = BX_CPU_THIS_PTR mem->getHostMemAddr(paddr, BX_READ); -+ -+ // Check that native host access was not vetoed for that page, and -+ // that the address is word aligned. -+ if ( hostAddrSrc && ! (paddr & 1) ) { -+ // See how many words can fit in the rest of this page. -+ wordsCanFit = (0x1000 - (paddr & 0xfff)) >> 1; -+ // Restrict word count to the number that will fit in this page. -+ if (wordCount > wordsCanFit) -+ wordCount = wordsCanFit; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (wordCount) { -+ unsigned transferLen; -+ Bit32u roomSrc; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = wordCount<<1; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(srcSegPtr->cache.valid & SegAccessROK) ) { -+ goto noAcceleration; -+ } -+ roomSrc = (srcSegPtr->cache.u.segment.limit_scaled - esi) + 1; -+ if ( roomSrc < transferLen ) { -+ goto noAcceleration; -+ } -+ -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -2; -+ else -+ pointerDelta = 2; -+ for (j=0; jas_32) -+ ECX -= (wordCount-1); -+ else -+ CX -= (wordCount-1); -+ incr = wordCount << 1; // count * 2. -+ goto doIncr; -+ } -+ } -+ } -+ } -+#endif // __i386__ -+#endif -+ -+noAcceleration: -+ - read_virtual_word(seg, esi, &value16); - - BX_OUTP(DX, value16, 2); - incr = 2; - } -+ -+#if (BX_DEBUGGER == 0) -+doIncr: -+#endif - - if (i->as_32) { - if (BX_CPU_THIS_PTR eflags.df) -Index: cpu/string.cc -=================================================================== -RCS file: /cvsroot/bochs/bochs/cpu/string.cc,v -retrieving revision 1.5 -diff -u -r1.5 string.cc ---- cpu/string.cc 3 Oct 2001 13:10:37 -0000 1.5 -+++ cpu/string.cc 29 Aug 2002 16:20:36 -0000 -@@ -34,6 +34,8 @@ - #define LOG_THIS BX_CPU_THIS_PTR - - -+ -+ - /* MOVSB ES:[EDI], DS:[ESI] DS may be overridden - * mov string from DS:[ESI] into ES:[EDI] - */ -@@ -80,24 +82,149 @@ - else - #endif /* BX_CPU_LEVEL >= 3 */ - { /* 16 bit address mode */ -+ unsigned incr; - Bit16u si, di; - - si = SI; - di = DI; - -+#if (BX_DEBUGGER == 0) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u byteCount; -+ bx_segment_reg_t *srcSegPtr, *dstSegPtr; -+ Bit32u laddrDst, laddrSrc, paddrDst, paddrSrc; -+ -+ if (i->as_32) -+ byteCount = ECX; -+ else -+ byteCount = CX; -+ srcSegPtr = &BX_CPU_THIS_PTR sregs[seg]; -+ dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SREG_ES]; -+ -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ read_virtual_checks(srcSegPtr, si, 1); -+ laddrSrc = srcSegPtr->cache.u.segment.base + si; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrSrc = dtranslate_linear(laddrSrc, CPL==3, BX_READ); -+ } -+ else { -+ paddrSrc = laddrSrc; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrSrc = A20ADDR(paddrSrc); -+ -+ write_virtual_checks(dstSegPtr, di, 1); -+ laddrDst = dstSegPtr->cache.u.segment.base + di; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrDst = dtranslate_linear(laddrDst, CPL==3, BX_WRITE); -+ } -+ else { -+ paddrDst = laddrDst; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrDst = A20ADDR(paddrDst); -+ -+ if (byteCount) { -+ Bit32u bytesCanFitSrc, bytesCanFitDst; -+ Bit8u *hostAddrSrc, *hostAddrDst; -+ -+ hostAddrSrc = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrSrc, BX_READ); -+ hostAddrDst = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrDst, BX_WRITE); -+ -+ if ( hostAddrSrc && hostAddrDst ) { -+ // See how many bytes can fit in the rest of this page. -+ bytesCanFitSrc = (0x1000 - (paddrSrc & 0xfff)); -+ bytesCanFitDst = (0x1000 - (paddrDst & 0xfff)); -+ // Restrict count to the number that will fit in either -+ // source or dest pages. -+ if (byteCount > bytesCanFitSrc) -+ byteCount = bytesCanFitSrc; -+ if (byteCount > bytesCanFitDst) -+ byteCount = bytesCanFitDst; -+ if (byteCount > bx_pc_system.num_cpu_ticks_left) -+ byteCount = bx_pc_system.num_cpu_ticks_left; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (byteCount) { -+ unsigned transferLen; -+ Bit32u roomSrc, roomDst; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = byteCount; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(srcSegPtr->cache.valid & SegAccessROK) || -+ !(dstSegPtr->cache.valid & SegAccessWOK) ) { -+ goto noAcceleration16; -+ } -+ roomSrc = (srcSegPtr->cache.u.segment.limit_scaled - si) + 1; -+ roomDst = (dstSegPtr->cache.u.segment.limit_scaled - di) + 1; -+ if ( (roomSrc < transferLen) || (roomDst < transferLen) ) { -+ goto noAcceleration16; -+ } -+ -+ // Transfer data directly using host addresses. -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -1; -+ else -+ pointerDelta = 1; -+ for (j=0; jas_32) -+ ECX -= (byteCount-1); -+ else -+ CX -= (byteCount-1); -+ incr = byteCount; -+ goto doIncr16; -+ } -+ } -+ } -+ } -+#endif -+ -+noAcceleration16: -+ - read_virtual_byte(seg, si, &temp8); - - write_virtual_byte(BX_SEG_REG_ES, di, &temp8); -+ incr = 1; -+ -+doIncr16: - - if (BX_CPU_THIS_PTR eflags.df) { - /* decrement SI, DI */ -- si--; -- di--; -+ si -= incr; -+ di -= incr; - } - else { - /* increment SI, DI */ -- si++; -- di++; -+ si += incr; -+ di += incr; - } - - SI = si; -@@ -109,7 +236,7 @@ - BX_CPU_C::MOVSW_XvYv(BxInstruction_t *i) - { - unsigned seg; -- -+ unsigned incr; - - if (!BX_NULL_SEG_REG(i->seg)) { - seg = i->seg; -@@ -128,19 +255,146 @@ - edi = EDI; - - if (i->os_32) { -+ -+#if (BX_DEBUGGER == 0) -+#if (defined(__i386__) && __i386__) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u dwordCount; -+ bx_segment_reg_t *srcSegPtr, *dstSegPtr; -+ Bit32u laddrDst, laddrSrc, paddrDst, paddrSrc; -+ -+ if (i->as_32) -+ dwordCount = ECX; -+ else -+ dwordCount = CX; -+ srcSegPtr = &BX_CPU_THIS_PTR sregs[seg]; -+ dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SREG_ES]; -+ -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ read_virtual_checks(srcSegPtr, esi, 4); -+ laddrSrc = srcSegPtr->cache.u.segment.base + esi; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrSrc = dtranslate_linear(laddrSrc, CPL==3, BX_READ); -+ } -+ else { -+ paddrSrc = laddrSrc; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrSrc = A20ADDR(paddrSrc); -+ -+ write_virtual_checks(dstSegPtr, edi, 4); -+ laddrDst = dstSegPtr->cache.u.segment.base + edi; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrDst = dtranslate_linear(laddrDst, CPL==3, BX_WRITE); -+ } -+ else { -+ paddrDst = laddrDst; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrDst = A20ADDR(paddrDst); -+ -+ if (dwordCount) { -+ Bit32u dwordsCanFitSrc, dwordsCanFitDst; -+ Bit8u *hostAddrSrc, *hostAddrDst; -+ -+ hostAddrSrc = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrSrc, BX_READ); -+ hostAddrDst = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrDst, BX_WRITE); -+ -+ if ( hostAddrSrc && hostAddrDst ) { -+ // See how many dwords can fit in the rest of this page. -+ dwordsCanFitSrc = (0x1000 - (paddrSrc & 0xfff)) >> 2; -+ dwordsCanFitDst = (0x1000 - (paddrDst & 0xfff)) >> 2; -+ // Restrict dword count to the number that will fit in either -+ // source or dest pages. -+ if (dwordCount > dwordsCanFitSrc) -+ dwordCount = dwordsCanFitSrc; -+ if (dwordCount > dwordsCanFitDst) -+ dwordCount = dwordsCanFitDst; -+ if (dwordCount > bx_pc_system.num_cpu_ticks_left) -+ dwordCount = bx_pc_system.num_cpu_ticks_left; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (dwordCount) { -+ unsigned transferLen; -+ Bit32u roomSrc, roomDst; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = dwordCount<<2; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(srcSegPtr->cache.valid & SegAccessROK) || -+ !(dstSegPtr->cache.valid & SegAccessWOK) ) { -+ goto noAcceleration32; -+ } -+ roomSrc = (srcSegPtr->cache.u.segment.limit_scaled - esi) + 1; -+ roomDst = (dstSegPtr->cache.u.segment.limit_scaled - edi) + 1; -+ if ( (roomSrc < transferLen) || (roomDst < transferLen) ) { -+ goto noAcceleration32; -+ } -+ -+ // Transfer data directly using host addresses. -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -4; -+ else -+ pointerDelta = 4; -+ for (j=0; jas_32) -+ ECX -= (dwordCount-1); -+ else -+ CX -= (dwordCount-1); -+ incr = dwordCount << 2; // count * 4. -+ goto doIncr32; -+ } -+ } -+ } -+ } -+#endif // __i386__ -+#endif -+ -+noAcceleration32: -+ - read_virtual_dword(seg, esi, &temp32); - - write_virtual_dword(BX_SEG_REG_ES, edi, &temp32); -+ incr = 4; -+ -+doIncr32: - - if (BX_CPU_THIS_PTR eflags.df) { - /* decrement ESI */ -- esi -= 4; -- edi -= 4; -+ esi -= incr; -+ edi -= incr; - } - else { - /* increment ESI */ -- esi += 4; -- edi += 4; -+ esi += incr; -+ edi += incr; - } - } /* if (i->os_32) ... */ - else { /* 16 bit opsize mode */ -@@ -198,19 +452,145 @@ - { /* 16 bit opsize mode */ - Bit16u temp16; - -+#if (BX_DEBUGGER == 0) -+#if (defined(__i386__) && __i386__) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u wordCount; -+ bx_segment_reg_t *srcSegPtr, *dstSegPtr; -+ Bit32u laddrDst, laddrSrc, paddrDst, paddrSrc; -+ -+ if (i->as_32) -+ wordCount = ECX; -+ else -+ wordCount = CX; -+ srcSegPtr = &BX_CPU_THIS_PTR sregs[seg]; -+ dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SREG_ES]; -+ -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ read_virtual_checks(srcSegPtr, si, 2); -+ laddrSrc = srcSegPtr->cache.u.segment.base + si; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrSrc = dtranslate_linear(laddrSrc, CPL==3, BX_READ); -+ } -+ else { -+ paddrSrc = laddrSrc; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrSrc = A20ADDR(paddrSrc); -+ -+ write_virtual_checks(dstSegPtr, di, 2); -+ laddrDst = dstSegPtr->cache.u.segment.base + di; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrDst = dtranslate_linear(laddrDst, CPL==3, BX_WRITE); -+ } -+ else { -+ paddrDst = laddrDst; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrDst = A20ADDR(paddrDst); -+ -+ if (wordCount) { -+ Bit32u wordsCanFitSrc, wordsCanFitDst; -+ Bit8u *hostAddrSrc, *hostAddrDst; -+ -+ hostAddrSrc = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrSrc, BX_READ); -+ hostAddrDst = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrDst, BX_WRITE); -+ -+ if ( hostAddrSrc && hostAddrDst ) { -+ // See how many words can fit in the rest of this page. -+ wordsCanFitSrc = (0x1000 - (paddrSrc & 0xfff)) >> 1; -+ wordsCanFitDst = (0x1000 - (paddrDst & 0xfff)) >> 1; -+ // Restrict dword count to the number that will fit in either -+ // source or dest pages. -+ if (wordCount > wordsCanFitSrc) -+ wordCount = wordsCanFitSrc; -+ if (wordCount > wordsCanFitDst) -+ wordCount = wordsCanFitDst; -+ if (wordCount > bx_pc_system.num_cpu_ticks_left) -+ wordCount = bx_pc_system.num_cpu_ticks_left; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (wordCount) { -+ unsigned transferLen; -+ Bit32u roomSrc, roomDst; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = wordCount<<1; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(srcSegPtr->cache.valid & SegAccessROK) || -+ !(dstSegPtr->cache.valid & SegAccessWOK) ) { -+ goto noAcceleration16; -+ } -+ roomSrc = (srcSegPtr->cache.u.segment.limit_scaled - si) + 1; -+ roomDst = (dstSegPtr->cache.u.segment.limit_scaled - di) + 1; -+ if ( (roomSrc < transferLen) || (roomDst < transferLen) ) { -+ goto noAcceleration16; -+ } -+ -+ // Transfer data directly using host addresses. -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -2; -+ else -+ pointerDelta = 2; -+ for (j=0; jas_32) -+ ECX -= (wordCount-1); -+ else -+ CX -= (wordCount-1); -+ incr = wordCount << 1; // count * 2. -+ goto doIncr16; -+ } -+ } -+ } -+ } -+#endif // __i386__ -+#endif -+ -+noAcceleration16: -+ - read_virtual_word(seg, si, &temp16); - - write_virtual_word(BX_SEG_REG_ES, di, &temp16); -+ incr = 2; -+ -+doIncr16: - - if (BX_CPU_THIS_PTR eflags.df) { - /* decrement SI, DI */ -- si -= 2; -- di -= 2; -+ si -= incr; -+ di -= incr; - } - else { - /* increment SI, DI */ -- si += 2; -- di += 2; -+ si += incr; -+ di += incr; - } - } - -@@ -593,48 +973,142 @@ - BX_CPU_C::STOSB_YbAL(BxInstruction_t *i) - { - Bit8u al; -+ Bit32u edi; -+ unsigned incr; - - #if BX_CPU_LEVEL >= 3 - if (i->as_32) { -- Bit32u edi; -- - edi = EDI; -- -- al = AL; -- write_virtual_byte(BX_SEG_REG_ES, edi, &al); -- -- if (BX_CPU_THIS_PTR eflags.df) { -- /* decrement EDI */ -- edi--; -- } -- else { -- /* increment EDI */ -- edi++; -- } -- -- EDI = edi; - } - else - #endif /* BX_CPU_LEVEL >= 3 */ - { /* 16bit address size */ -- Bit16u di; -+ edi = DI; -+ } -+ al = AL; - -- di = DI; - -- al = AL; -- write_virtual_byte(BX_SEG_REG_ES, di, &al); -+#if (BX_DEBUGGER == 0) -+ /* If conditions are right, we can transfer IO to physical memory -+ * in a batch, rather than one instruction at a time. -+ */ -+ if (i->rep_used && !BX_CPU_THIS_PTR async_event) { -+ Bit32u byteCount; -+ bx_segment_reg_t *dstSegPtr; -+ Bit32u laddrDst, paddrDst; -+ -+ if (i->as_32) -+ byteCount = ECX; -+ else -+ byteCount = CX; -+ dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SREG_ES]; -+ -+ // Do segment checks for the 1st word. We do not want to -+ // trip an exception beyond this, because the address would -+ // be incorrect. After we know how many bytes we will directly -+ // transfer, we can do the full segment limit check ourselves -+ // without generating an exception. -+ write_virtual_checks(dstSegPtr, edi, 1); -+ laddrDst = dstSegPtr->cache.u.segment.base + edi; -+ if (BX_CPU_THIS_PTR cr0.pg) { -+ paddrDst = dtranslate_linear(laddrDst, CPL==3, BX_WRITE); -+ } -+ else { -+ paddrDst = laddrDst; -+ } -+ // If we want to write directly into the physical memory array, -+ // we need the A20 address. -+ paddrDst = A20ADDR(paddrDst); -+ -+ if (byteCount) { -+ Bit32u bytesCanFitDst; -+ Bit8u *hostAddrDst; -+ -+ hostAddrDst = BX_CPU_THIS_PTR mem->getHostMemAddr(paddrDst, BX_WRITE); -+ -+ if ( hostAddrDst ) { -+ // See how many bytes can fit in the rest of this page. -+ bytesCanFitDst = (0x1000 - (paddrDst & 0xfff)); -+ // Restrict count to the number that will fit in either -+ // source or dest pages. -+ if (byteCount > bytesCanFitDst) -+ byteCount = bytesCanFitDst; -+ if (byteCount > bx_pc_system.num_cpu_ticks_left) -+ byteCount = bx_pc_system.num_cpu_ticks_left; -+ -+ // If after all the restrictions, there is anything left to do... -+ if (byteCount) { -+ unsigned transferLen; -+ Bit32u roomDst; -+ unsigned j; -+ unsigned pointerDelta; -+ -+ transferLen = byteCount; // Number bytes to transfer. -+ -+ // Before we copy memory, we need to make sure that the segments -+ // allow the accesses up to the given source and dest offset. If -+ // the cache.valid bits have SegAccessWOK and ROK, we know that -+ // the cache is valid for those operations, and that the segments -+ // are non-expand down (thus we can make a simple limit check). -+ if ( !(dstSegPtr->cache.valid & SegAccessWOK) ) { -+ goto noAcceleration16; -+ } -+ roomDst = (dstSegPtr->cache.u.segment.limit_scaled - edi) + 1; -+ if ( roomDst < transferLen ) { -+ goto noAcceleration16; -+ } -+ -+ // Transfer data directly using host addresses. -+ if (BX_CPU_THIS_PTR eflags.df) -+ pointerDelta = (unsigned) -1; -+ else -+ pointerDelta = 1; -+ for (j=0; jas_32) -+ ECX -= (byteCount-1); -+ else -+ CX -= (byteCount-1); -+ incr = byteCount; -+ goto doIncr16; -+ } -+ } -+ } -+ } -+#endif -+ -+noAcceleration16: -+ -+ write_virtual_byte(BX_SEG_REG_ES, edi, &al); -+ incr = 1; -+ -+doIncr16: - - if (BX_CPU_THIS_PTR eflags.df) { - /* decrement EDI */ -- di--; -+ edi -= incr; - } - else { - /* increment EDI */ -- di++; -+ edi += incr; - } - -- DI = di; -- } -+#if BX_CPU_LEVEL >= 3 -+ if (i->as_32) -+ EDI = edi; -+ else -+#endif -+ DI = edi; - } - - void -Index: memory/memory.h -=================================================================== -RCS file: /cvsroot/bochs/bochs/memory/memory.h,v -retrieving revision 1.6 -diff -u -r1.6 memory.h ---- memory/memory.h 3 Oct 2001 13:10:38 -0000 1.6 -+++ memory/memory.h 29 Aug 2002 16:20:38 -0000 -@@ -65,6 +65,7 @@ - BX_MEM_SMF Boolean dbg_crc32( - unsigned long (*f)(unsigned char *buf, int len), - Bit32u addr1, Bit32u addr2, Bit32u *crc); -+ BX_MEM_SMF Bit8u * getHostMemAddr(Bit32u a20Addr, unsigned op); - }; - - #if BX_PROVIDE_CPU_MEMORY==1 -Index: memory/misc_mem.cc -=================================================================== -RCS file: /cvsroot/bochs/bochs/memory/misc_mem.cc,v -retrieving revision 1.23 -diff -u -r1.23 misc_mem.cc ---- memory/misc_mem.cc 18 Aug 2002 08:53:26 -0000 1.23 -+++ memory/misc_mem.cc 29 Aug 2002 16:20:39 -0000 -@@ -282,3 +282,32 @@ - - return(1); - } -+ -+ Bit8u * -+BX_MEM_C::getHostMemAddr(Bit32u a20Addr, unsigned op) -+ // Return a host address corresponding to the guest physical memory -+ // address (with A20 already applied), given that the calling -+ // code will perform an 'op' operation. This address will be -+ // used for direct access to guest memory as an acceleration by -+ // a few instructions, like REP {MOV, INS, OUTS, etc}. -+ // Values of 'op' are { BX_READ, BX_WRITE, BX_RW }. -+ -+ // The other assumption is that the calling code _only_ accesses memory -+ // directly within the page that encompasses the address requested. -+{ -+#if BX_PCI_SUPPORT -+#error "Fix getHostMemAddr for PCI support." -+#endif -+ if ( a20Addr >= BX_MEM_THIS len ) -+ return(NULL); // Error, requested addr is out of bounds. -+ if (op == BX_READ) { -+ if ( (a20Addr < 0xa0000) || (a20Addr > 0xbffff) ) -+ return( (Bit8u *) & vector[a20Addr] ); -+ return(NULL); // Vetoed! Mem mapped IO (VGA) -+ } -+ else { // op == {BX_WRITE, BX_RW} -+ if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) ) -+ return( (Bit8u *) & vector[a20Addr] ); -+ return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs -+ } -+} diff --git a/bochs/patches/patch.seg-checks b/bochs/patches/patch.seg-checks deleted file mode 100644 index e595d65b2..000000000 --- a/bochs/patches/patch.seg-checks +++ /dev/null @@ -1,438 +0,0 @@ ----------------------------------------------------------------------- -Patch name: patch.seg-checks -Author: Kevin Lawton -Date: Tue, 27 Aug 2002 15:47:14 -0700 (PDT) - -Detailed description: -Here's some pretty simple mods that speed things up some. -The memory access routines in access.cc now skip the segment -type check if they've seen the same R or W operation on that -segment before, plus do their limit check if the access check -is not needed. This eliminates the call to write_virtual_checks() -and read_virtual_check() for most cases. - -The limit check is a little faster as well. - -There is a field in each segment cache called "valid". Since -this was always loaded with 0 or 1 when the segment is reloaded -or invalidated due to a context change, this made for an easy -place to store a couple extra bits to record when a read and -a write access to that seg has occurred. Other code that -sets "valid" to 0 or 1 wipes out the R&W bits, which is good, -since at least one new access check must occur before succeeding -accesses can eliminate it. - -I'll let you folks benchmark the difference. One test -prog I ran gained 6%, but I'm not sure if it's register -intensive (and thus wouldn't gain much) vs memory access -intensive. - -Patch was created with: - cvs diff -u -Apply patch to what version: - cvs checked out on DATE, release version VER -Instructions: - To patch, go to main bochs directory. - Type "patch -p0 < THIS_PATCH_FILE". ----------------------------------------------------------------------- -Index: cpu/access.cc -=================================================================== -RCS file: /cvsroot/bochs/bochs/cpu/access.cc,v -retrieving revision 1.12 -diff -u -r1.12 access.cc ---- cpu/access.cc 3 Oct 2001 13:10:37 -0000 1.12 -+++ cpu/access.cc 27 Aug 2002 22:28:19 -0000 -@@ -38,14 +38,12 @@ - - - -- - void - BX_CPU_C::write_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, - unsigned length) - { - Bit32u upper_limit; - -- - if ( protected_mode() ) { - if ( seg->cache.valid==0 ) { - BX_ERROR(("seg = %s", BX_CPU_THIS_PTR strseg(seg))); -@@ -81,6 +79,16 @@ - exception(int_number(seg), 0, 0); - return; - } -+ if (seg->cache.u.segment.limit_scaled >= 3) { -+ // 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; -+ } - break; - - case 6: case 7: /* read write, expand down */ -@@ -109,6 +117,10 @@ - if (seg == & BX_CPU_THIS_PTR sregs[2]) exception(BX_SS_EXCEPTION, 0, 0); - else exception(BX_GP_EXCEPTION, 0, 0); - } -+ if (seg->cache.u.segment.limit_scaled >= 3) { -+ // Mark cache as being OK type for succeeding writes. See notes above. -+ seg->cache.valid |= SegAccessWOK; -+ } - } - } - -@@ -118,7 +130,6 @@ - { - Bit32u upper_limit; - -- - if ( protected_mode() ) { - if ( seg->cache.valid==0 ) { - BX_ERROR(("seg = %s", BX_CPU_THIS_PTR strseg(seg))); -@@ -148,6 +159,11 @@ - exception(int_number(seg), 0, 0); - return; - } -+ if (seg->cache.u.segment.limit_scaled >= 3) { -+ // Mark cache as being OK type for succeeding writes. See notes for -+ // write checks; similar code. -+ seg->cache.valid |= SegAccessROK; -+ } - break; - - case 2: case 3: /* read/write */ -@@ -157,6 +173,11 @@ - exception(int_number(seg), 0, 0); - return; - } -+ if (seg->cache.u.segment.limit_scaled >= 3) { -+ // Mark cache as being OK type for succeeding writes. See notes for -+ // write checks; similar code. -+ seg->cache.valid |= SegAccessROK; -+ } - break; - - case 4: case 5: /* read only, expand down */ -@@ -206,6 +227,11 @@ - if (seg == & BX_CPU_THIS_PTR sregs[2]) exception(BX_SS_EXCEPTION, 0, 0); - else exception(BX_GP_EXCEPTION, 0, 0); - } -+ if (seg->cache.u.segment.limit_scaled >= 3) { -+ // Mark cache as being OK type for succeeding writes. See notes for -+ // write checks; similar code. -+ seg->cache.valid |= SegAccessROK; -+ } - return; - } - } -@@ -238,13 +264,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 1); -- -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 1, BX_WRITE); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset <= seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 1, BX_WRITE); - -- // all checks OK -- access_linear(laddr, 1, CPL==3, BX_WRITE, (void *) data); -+ // all checks OK -+ access_linear(laddr, 1, CPL==3, BX_WRITE, (void *) data); -+ return; -+ } -+ } -+ write_virtual_checks(seg, offset, 1); -+ goto accessOK; - } - - void -@@ -254,13 +286,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 2); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset < seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 2, BX_WRITE); - -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 2, BX_WRITE); -- -- // all checks OK -- access_linear(laddr, 2, CPL==3, BX_WRITE, (void *) data); -+ // all checks OK -+ access_linear(laddr, 2, CPL==3, BX_WRITE, (void *) data); -+ return; -+ } -+ } -+ write_virtual_checks(seg, offset, 2); -+ goto accessOK; - } - - void -@@ -270,13 +308,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 4); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset < (seg->cache.u.segment.limit_scaled-2)) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 4, BX_WRITE); - -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 4, BX_WRITE); -- -- // all checks OK -- access_linear(laddr, 4, CPL==3, BX_WRITE, (void *) data); -+ // all checks OK -+ access_linear(laddr, 4, CPL==3, BX_WRITE, (void *) data); -+ return; -+ } -+ } -+ write_virtual_checks(seg, offset, 4); -+ goto accessOK; - } - - void -@@ -286,13 +330,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- read_virtual_checks(seg, offset, 1); -+ if (seg->cache.valid & SegAccessROK) { -+ if (offset <= seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 1, BX_READ); - -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 1, BX_READ); -- -- // all checks OK -- access_linear(laddr, 1, CPL==3, BX_READ, (void *) data); -+ // all checks OK -+ access_linear(laddr, 1, CPL==3, BX_READ, (void *) data); -+ return; -+ } -+ } -+ read_virtual_checks(seg, offset, 1); -+ goto accessOK; - } - - -@@ -303,13 +353,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- read_virtual_checks(seg, offset, 2); -- -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 2, BX_READ); -+ if (seg->cache.valid & SegAccessROK) { -+ if (offset < seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 2, BX_READ); - -- // all checks OK -- access_linear(laddr, 2, CPL==3, BX_READ, (void *) data); -+ // all checks OK -+ access_linear(laddr, 2, CPL==3, BX_READ, (void *) data); -+ return; -+ } -+ } -+ read_virtual_checks(seg, offset, 2); -+ goto accessOK; - } - - -@@ -320,13 +376,19 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- read_virtual_checks(seg, offset, 4); -- -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 4, BX_READ); -+ if (seg->cache.valid & SegAccessROK) { -+ if (offset < (seg->cache.u.segment.limit_scaled-2)) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 4, BX_READ); - -- // all checks OK -- access_linear(laddr, 4, CPL==3, BX_READ, (void *) data); -+ // all checks OK -+ access_linear(laddr, 4, CPL==3, BX_READ, (void *) data); -+ return; -+ } -+ } -+ read_virtual_checks(seg, offset, 4); -+ goto accessOK; - } - - ////////////////////////////////////////////////////////////// -@@ -341,23 +403,29 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 1); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset <= seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 1, BX_READ); - -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 1, BX_READ); -- -- // all checks OK -+ // all checks OK - #if BX_CPU_LEVEL >= 3 -- if (BX_CPU_THIS_PTR cr0.pg) -- access_linear(laddr, 1, CPL==3, BX_RW, (void *) data); -- else -+ if (BX_CPU_THIS_PTR cr0.pg) -+ access_linear(laddr, 1, CPL==3, BX_RW, (void *) data); -+ else - #endif -- { -- BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -- BX_INSTR_LIN_READ(laddr, laddr, 1); -- BX_INSTR_LIN_WRITE(laddr, laddr, 1); -- BX_CPU_THIS_PTR mem->read_physical(this, laddr, 1, (void *) data); -+ { -+ BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -+ BX_INSTR_LIN_READ(laddr, laddr, 1); -+ BX_INSTR_LIN_WRITE(laddr, laddr, 1); -+ BX_CPU_THIS_PTR mem->read_physical(this, laddr, 1, (void *) data); -+ } -+ return; -+ } - } -+ write_virtual_checks(seg, offset, 1); -+ goto accessOK; - } - - -@@ -368,23 +436,29 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 2); -- -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 2, BX_READ); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset < seg->cache.u.segment.limit_scaled) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 2, BX_READ); - -- // all checks OK -+ // all checks OK - #if BX_CPU_LEVEL >= 3 -- if (BX_CPU_THIS_PTR cr0.pg) -- access_linear(laddr, 2, CPL==3, BX_RW, (void *) data); -- else -+ if (BX_CPU_THIS_PTR cr0.pg) -+ access_linear(laddr, 2, CPL==3, BX_RW, (void *) data); -+ else - #endif -- { -- BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -- BX_INSTR_LIN_READ(laddr, laddr, 2); -- BX_INSTR_LIN_WRITE(laddr, laddr, 2); -- BX_CPU_THIS_PTR mem->read_physical(this, laddr, 2, data); -+ { -+ BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -+ BX_INSTR_LIN_READ(laddr, laddr, 2); -+ BX_INSTR_LIN_WRITE(laddr, laddr, 2); -+ BX_CPU_THIS_PTR mem->read_physical(this, laddr, 2, data); -+ } -+ return; -+ } - } -+ write_virtual_checks(seg, offset, 2); -+ goto accessOK; - } - - void -@@ -394,23 +468,29 @@ - bx_segment_reg_t *seg; - - seg = &BX_CPU_THIS_PTR sregs[s]; -- write_virtual_checks(seg, offset, 4); -- -- laddr = seg->cache.u.segment.base + offset; -- BX_INSTR_MEM_DATA(laddr, 4, BX_READ); -+ if (seg->cache.valid & SegAccessWOK) { -+ if (offset < (seg->cache.u.segment.limit_scaled-2)) { -+accessOK: -+ laddr = seg->cache.u.segment.base + offset; -+ BX_INSTR_MEM_DATA(laddr, 4, BX_READ); - -- // all checks OK -+ // all checks OK - #if BX_CPU_LEVEL >= 3 -- if (BX_CPU_THIS_PTR cr0.pg) -- access_linear(laddr, 4, CPL==3, BX_RW, (void *) data); -- else -+ if (BX_CPU_THIS_PTR cr0.pg) -+ access_linear(laddr, 4, CPL==3, BX_RW, (void *) data); -+ else - #endif -- { -- BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -- BX_INSTR_LIN_READ(laddr, laddr, 4); -- BX_INSTR_LIN_WRITE(laddr, laddr, 4); -- BX_CPU_THIS_PTR mem->read_physical(this, laddr, 4, data); -+ { -+ BX_CPU_THIS_PTR address_xlation.paddress1 = laddr; -+ BX_INSTR_LIN_READ(laddr, laddr, 4); -+ BX_INSTR_LIN_WRITE(laddr, laddr, 4); -+ BX_CPU_THIS_PTR mem->read_physical(this, laddr, 4, data); -+ } -+ return; -+ } - } -+ write_virtual_checks(seg, offset, 4); -+ goto accessOK; - } - - void -Index: cpu/cpu.h -=================================================================== -RCS file: /cvsroot/bochs/bochs/cpu/cpu.h,v -retrieving revision 1.22 -diff -u -r1.22 cpu.h ---- cpu/cpu.h 5 Jun 2002 21:51:30 -0000 1.22 -+++ cpu/cpu.h 27 Aug 2002 22:28:24 -0000 -@@ -347,7 +347,13 @@ - - - typedef struct { -- Boolean valid; /* 0 = invalid, 1 = valid */ -+ -+#define SegValidCache 0x1 -+#define SegAccessROK 0x2 -+#define SegAccessWOK 0x4 -+ Boolean valid; // Holds above values, Or'd together. Used to -+ // hold only 0 or 1. -+ - Boolean p; /* present */ - Bit8u dpl; /* descriptor privilege level 0..3 */ - Boolean segment; /* 0 = system/gate, 1 = data/code segment */