- 10% emulation speedup with handlers chaining optimization implemented. The

feature is enabled by default when configure with --enable-all-optimizations
    option, to disable handlers chaining speedups configure with
        --disable-handlers-chaining
This commit is contained in:
Stanislav Shwartsman 2011-08-21 14:31:08 +00:00
parent af1e3a6f80
commit 13feb0772a
16 changed files with 218 additions and 62 deletions

View File

@ -11,6 +11,12 @@ Bochs repository moved to the SVN version control !
or read docs for list of supported configurations or more details.
* It is also possible to choose the CPU to emulate from Bochs command line
using new command line parameter -cpu <cpu_name>.
- 10% emulation speedup with handlers chaining optimization implemented. The
feature is enabled by default when configure with --enable-all-optimizations
option, to disable handlers chaining speedups configure with
--disable-handlers-chaining
- Implemented Supervisor Mode Execution Protection (SMEP), the feature can
be enabled using .bochsrc CPUID option.
- Added support for XSAVEOPT instruction, the instruction can be enabled

View File

@ -670,7 +670,12 @@ typedef
#error "AVX require x86-64 support"
#endif
#define BX_SupportRepeatSpeedups 0
#define BX_SUPPORT_REPEAT_SPEEDUPS 0
#define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 0
#if (BX_SUPPORT_SMP || BX_DEBUGGER || BX_GDBSTUB) && BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
#error "Handler-chanining-speedups are not supported together with internal debugger or SMP !"
#endif
#if BX_SUPPORT_3DNOW
#define BX_CPU_VENDOR_INTEL 0

106
bochs/configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in Id: configure.in 10594 2011-08-17 18:27:49Z sshwarts .
# From configure.in Id: configure.in 10603 2011-08-18 18:55:22Z sshwarts .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68.
#
@ -963,6 +963,7 @@ enable_usb_xhci
enable_pnic
enable_repeat_speedups
enable_fast_function_calls
enable_handlers_chaining_speedups
enable_configurable_msrs
enable_show_ips
enable_cpp
@ -1679,6 +1680,7 @@ Optional Features:
--enable-pnic enable PCI pseudo NIC support
--enable-repeat-speedups support repeated IO and mem copy speedups
--enable-fast-function-calls support for fast function calls (gcc on x86 only)
--enable-handlers-chaining support handlers-chaining emulation speedups
--enable-configurable-msrs support for configurable MSR registers
--enable-show-ips show IPS in Bochs log file
--enable-cpp use .cpp as C++ suffix
@ -5106,7 +5108,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5109 "configure"' > conftest.$ac_ext
echo '#line 5111 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@ -6794,11 +6796,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6797: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6799: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6801: \$? = $ac_status" >&5
echo "$as_me:6803: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -7027,11 +7029,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7030: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7032: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7034: \$? = $ac_status" >&5
echo "$as_me:7036: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -7094,11 +7096,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7097: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7099: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7101: \$? = $ac_status" >&5
echo "$as_me:7103: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -8884,7 +8886,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 8887 "configure"
#line 8889 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -8982,7 +8984,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 8985 "configure"
#line 8987 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11097,11 +11099,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:11100: $lt_compile\"" >&5)
(eval echo "\"\$as_me:11102: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:11104: \$? = $ac_status" >&5
echo "$as_me:11106: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -11164,11 +11166,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:11167: $lt_compile\"" >&5)
(eval echo "\"\$as_me:11169: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:11171: \$? = $ac_status" >&5
echo "$as_me:11173: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -12189,7 +12191,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 12192 "configure"
#line 12194 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -12287,7 +12289,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 12290 "configure"
#line 12292 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13110,11 +13112,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:13113: $lt_compile\"" >&5)
(eval echo "\"\$as_me:13115: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:13117: \$? = $ac_status" >&5
echo "$as_me:13119: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -13177,11 +13179,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:13180: $lt_compile\"" >&5)
(eval echo "\"\$as_me:13182: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:13184: \$? = $ac_status" >&5
echo "$as_me:13186: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -15142,11 +15144,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:15145: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15147: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:15149: \$? = $ac_status" >&5
echo "$as_me:15151: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -15375,11 +15377,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:15378: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15380: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:15382: \$? = $ac_status" >&5
echo "$as_me:15384: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -15442,11 +15444,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:15445: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15447: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:15449: \$? = $ac_status" >&5
echo "$as_me:15451: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -17232,7 +17234,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 17235 "configure"
#line 17237 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -17330,7 +17332,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 17333 "configure"
#line 17335 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -19016,7 +19018,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 19019 "configure"
#line 19021 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -22425,6 +22427,29 @@ $as_echo "no" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for handlers chaining speedups" >&5
$as_echo_n "checking for handlers chaining speedups... " >&6; }
# Check whether --enable-handlers-chaining-speedups was given.
if test "${enable_handlers_chaining_speedups+set}" = set; then :
enableval=$enable_handlers_chaining_speedups; if test "$enableval" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
speedup_handlers_chaining=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
speedup_handlers_chaining=0
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
speedup_handlers_chaining=0
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking support for configurable MSR registers" >&5
$as_echo_n "checking support for configurable MSR registers... " >&6; }
# Check whether --enable-configurable-msrs was given.
@ -22667,13 +22692,14 @@ if test "$speedups_all" = 1; then
# Configure requested to force all options enabled.
speedup_repeat=1
speedup_fastcall=1
speedup_handlers_chaining=1
fi
if test "$speedup_repeat" = 1; then
$as_echo "#define BX_SupportRepeatSpeedups 1" >>confdefs.h
$as_echo "#define BX_SUPPORT_REPEAT_SPEEDUPS 1" >>confdefs.h
else
$as_echo "#define BX_SupportRepeatSpeedups 0" >>confdefs.h
$as_echo "#define BX_SUPPORT_REPEAT_SPEEDUPS 0" >>confdefs.h
fi
@ -22685,6 +22711,24 @@ else
fi
if test "$use_smp" = 1; then
echo "ERROR: with >1 processor handlers-chaining speedups are not supported yet"
exit 1
fi
if test "$bx_debugger" = 1; then
echo "ERROR: handlers-chaining speedups are not supported with internal debugger yet"
exit 1
fi
if test "$speedup_handlers_chaining" = 1; then
$as_echo "#define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 1" >>confdefs.h
else
$as_echo "#define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 0" >>confdefs.h
fi
READLINE_LIB=""
rl_without_curses_ok=no

View File

@ -942,6 +942,22 @@ AC_ARG_ENABLE(fast-function-calls,
]
)
AC_MSG_CHECKING(for handlers chaining speedups)
AC_ARG_ENABLE(handlers-chaining-speedups,
[ --enable-handlers-chaining support handlers-chaining emulation speedups],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
speedup_handlers_chaining=1
else
AC_MSG_RESULT(no)
speedup_handlers_chaining=0
fi],
[
AC_MSG_RESULT(no)
speedup_handlers_chaining=0
]
)
AC_MSG_CHECKING(support for configurable MSR registers)
AC_ARG_ENABLE(configurable-msrs,
[ --enable-configurable-msrs support for configurable MSR registers],
@ -1116,12 +1132,13 @@ if test "$speedups_all" = 1; then
# Configure requested to force all options enabled.
speedup_repeat=1
speedup_fastcall=1
speedup_handlers_chaining=1
fi
if test "$speedup_repeat" = 1; then
AC_DEFINE(BX_SupportRepeatSpeedups, 1)
AC_DEFINE(BX_SUPPORT_REPEAT_SPEEDUPS, 1)
else
AC_DEFINE(BX_SupportRepeatSpeedups, 0)
AC_DEFINE(BX_SUPPORT_REPEAT_SPEEDUPS, 0)
fi
if test "$speedup_fastcall" = 1; then
@ -1130,6 +1147,22 @@ else
AC_DEFINE(BX_FAST_FUNC_CALL, 0)
fi
if test "$use_smp" = 1; then
echo "ERROR: with >1 processor handlers-chaining speedups are not supported yet"
exit 1
fi
if test "$bx_debugger" = 1; then
echo "ERROR: handlers-chaining speedups are not supported with internal debugger yet"
exit 1
fi
if test "$speedup_handlers_chaining" = 1; then
AC_DEFINE(BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS, 1)
else
AC_DEFINE(BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS, 0)
fi
READLINE_LIB=""
rl_without_curses_ok=no

View File

@ -113,25 +113,22 @@ void BX_CPU_C::cpu_loop(Bit32u max_instr_count)
}
bxICacheEntry_c *entry = getICacheEntry();
bxInstruction_c *i = entry->i;
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0
bxInstruction_c *last = i + (entry->tlen);
#endif
for(;;) {
#if BX_DISASM
if (BX_CPU_THIS_PTR trace) {
// print the instruction that is about to be executed
debug_disasm_instruction(BX_CPU_THIS_PTR prev_rip);
}
#endif
BX_DEBUG_DISASM_INSTRUCTION();
// instruction decoding completed -> continue with execution
// want to allow changing of the instruction inside instrumentation callback
BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i);
RIP += i->ilen();
// when handlers chaining is enabled this single call will execute entire trace
BX_CPU_CALL_METHOD(i->execute, (i)); // might iterate repeat instruction
BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, i);
BX_TICK1_IF_SINGLE_PROCESSOR();
@ -149,11 +146,16 @@ void BX_CPU_C::cpu_loop(Bit32u max_instr_count)
break;
}
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
entry = getICacheEntry();
i = entry->i;
#else
if (++i == last) {
entry = getICacheEntry();
i = entry->i;
last = i + (entry->tlen);
}
#endif
}
} // while (1)
}

View File

@ -2930,6 +2930,9 @@ public: // for now...
BX_SMF BX_INSF_TYPE UndefinedOpcode(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF BX_INSF_TYPE BxError(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
BX_SMF BX_INSF_TYPE BxEndTrace(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#endif
#if BX_CPU_LEVEL >= 6
BX_SMF BX_INSF_TYPE BxNoSSE(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF BX_INSF_TYPE BxNoAVX(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
@ -3264,7 +3267,7 @@ public: // for now...
BX_SMF void branch_far64(bx_selector_t *selector,
bx_descriptor_t *descriptor, bx_address rip, Bit8u cpl);
#if BX_SupportRepeatSpeedups
#if BX_SUPPORT_REPEAT_SPEEDUPS
BX_SMF Bit32u FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff,
unsigned dstSeg, bx_address dstOff, Bit32u byteCount);
BX_SMF Bit32u FastRepMOVSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff,

View File

@ -37,7 +37,7 @@ BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near16(Bit16u new_IP)
EIP = new_IP;
#if !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0
// assert magic async_event to stop trace execution
BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
#endif

View File

@ -39,7 +39,7 @@ BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP
EIP = new_EIP;
#if !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0
// assert magic async_event to stop trace execution
BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
#endif

View File

@ -37,7 +37,7 @@ BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near64(bxInstruction_
RIP = new_RIP;
#if !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0
// assert magic async_event to stop trace execution
BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
#endif

View File

@ -32,6 +32,9 @@
// directly calls the /r form.
bx_define_opcode(BX_IA_ERROR, &BX_CPU_C::BxError, &BX_CPU_C::BxError, 0, 0)
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
bx_define_opcode(BX_INSERTED_OPCODE, &BX_CPU_C::BxError, &BX_CPU_C::BxError, 0, 0)
#endif
bx_define_opcode(BX_IA_AAA, NULL, &BX_CPU_C::AAA, 0, 0)
bx_define_opcode(BX_IA_AAD, NULL, &BX_CPU_C::AAD, 0, 0)

View File

@ -46,6 +46,22 @@ void handleSMC(bx_phy_address pAddr, Bit32u mask)
}
}
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
BX_INSF_TYPE BX_CPU_C::BxEndTrace(bxInstruction_c *i)
{
// do nothing, return to main cpu_loop
}
void genDummyICacheEntry(bxInstruction_c *i, BxExecutePtr_tR execute)
{
i->setILen(0);
i->setIaOpcode(BX_INSERTED_OPCODE);
i->execute = execute;
}
#endif
bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr)
{
bxICacheEntry_c *vc_hit = BX_CPU_THIS_PTR iCache.lookup_victim_cache(pAddr, BX_CPU_THIS_PTR fetchModeMask);
@ -99,6 +115,12 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBia
entry->traceMask = 0x80000000; /* last line in page */
pageWriteStampTable.markICacheMask(entry->pAddr, entry->traceMask);
pageWriteStampTable.markICacheMask(BX_CPU_THIS_PTR pAddrPage, 0x1);
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
entry->tlen++; /* Add the inserted end of trace opcode */
genDummyICacheEntry(++i, &BX_CPU_C::BxEndTrace);
#endif
BX_CPU_THIS_PTR iCache.commit_page_split_trace(BX_CPU_THIS_PTR pAddrPage, entry);
return entry;
}
@ -110,10 +132,11 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBia
#ifdef BX_INSTR_STORE_OPCODE_BYTES
i->set_opcode_bytes(fetchPtr);
#endif
BX_INSTR_OPCODE(BX_CPU_ID, i, fetchPtr, iLen,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, long64_mode());
i++;
traceMask |= 1 << (pageOffset >> 7);
traceMask |= 1 << ((pageOffset + iLen - 1) >> 7);
@ -123,11 +146,16 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBia
pAddr += iLen;
pageOffset += iLen;
fetchPtr += iLen;
i++;
// try to find a trace starting from current pAddr and merge
if (remainingInPage >= 15) // avoid merging with page split trace
if (mergeTraces(entry, i, pAddr)) break;
if (remainingInPage >= 15) { // avoid merging with page split trace
if (mergeTraces(entry, i, pAddr)) {
entry->traceMask |= traceMask;
pageWriteStampTable.markICacheMask(pAddr, entry->traceMask);
BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen);
return entry;
}
}
}
//BX_INFO(("commit trace %08x len=%d mask %08x", (Bit32u) entry->pAddr, entry->tlen, pageWriteStampTable.getFineGranularityMapping(entry->pAddr)));
@ -136,6 +164,11 @@ bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBia
pageWriteStampTable.markICacheMask(pAddr, entry->traceMask);
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
entry->tlen++; /* Add the inserted end of trace opcode */
genDummyICacheEntry(i, &BX_CPU_C::BxEndTrace);
#endif
BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen);
return entry;
@ -149,9 +182,15 @@ bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy
{
// determine max amount of instruction to take from another entry
unsigned max_length = e->tlen;
#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS
if (max_length + entry->tlen > BX_MAX_TRACE_LENGTH)
return 0;
#else
if (max_length + entry->tlen > BX_MAX_TRACE_LENGTH)
max_length = BX_MAX_TRACE_LENGTH - entry->tlen;
if(max_length == 0) return 0;
#endif
memcpy(i, e->i, sizeof(bxInstruction_c)*max_length);
entry->tlen += max_length;

View File

@ -104,7 +104,7 @@ extern bxPageWriteStampTable pageWriteStampTable;
#define BxICacheEntries (64 * 1024) // Must be a power of 2.
#define BxICacheMemPool (384 * 1024)
#define BX_MAX_TRACE_LENGTH 32
#define BX_MAX_TRACE_LENGTH 16
struct bxICacheEntry_c
{
@ -148,7 +148,8 @@ public:
BX_CPP_INLINE void alloc_trace(bxICacheEntry_c *e)
{
if (mpindex + BX_MAX_TRACE_LENGTH > BxICacheMemPool) {
// took +1 garbend for instruction chaining speedup (end-of-trace opcode)
if ((mpindex + BX_MAX_TRACE_LENGTH + 1) > BxICacheMemPool) {
flushICacheEntries();
}
e->i = &mpool[mpindex];
@ -159,7 +160,7 @@ public:
BX_CPP_INLINE void commit_page_split_trace(bx_phy_address paddr, bxICacheEntry_c *entry)
{
mpindex++; // commit_trace(1)
mpindex += entry->tlen;
// register page split entry
if (pageSplitIndex[nextPageSplitIndex].ppf != BX_ICACHE_INVALID_PHY_ADDRESS)

View File

@ -28,7 +28,26 @@ class bxInstruction_c;
typedef void BX_INSF_TYPE;
#define BX_NEXT_INSTR(i) { return; }
#if BX_DISASM
// print the instruction that is about to be executed
#define BX_DEBUG_DISASM_INSTRUCTION() \
if (BX_CPU_THIS_PTR trace) { debug_disasm_instruction(BX_CPU_THIS_PTR prev_rip); }
#else
#define BX_DEBUG_DISASM_INSTRUCTION() /* do nothing */
#endif
#define BX_NEXT_INSTR(i) { \
BX_CPU_THIS_PTR prev_rip = RIP; /* commit new RIP */ \
BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, i); \
BX_TICK1_IF_SINGLE_PROCESSOR(); \
if (BX_CPU_THIS_PTR async_event) return; \
++i; \
BX_DEBUG_DISASM_INSTRUCTION(); \
BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i); \
RIP += i->ilen(); \
return BX_CPU_CALL_METHOD(i->execute, (i)); \
}
#define BX_NEXT_TRACE(i) { return; }
// <TAG-TYPE-EXECUTEPTR-START>

View File

@ -31,7 +31,7 @@
// Repeat Speedups methods
//
#if BX_SupportRepeatSpeedups
#if BX_SUPPORT_REPEAT_SPEEDUPS
Bit32u BX_CPU_C::FastRepINSW(bxInstruction_c *i, bx_address dstOff, Bit16u port, Bit32u wordCount)
{
Bit32u wordsFitDst;
@ -312,7 +312,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW32_YwDX(bxInstruction_c *i)
Bit32u edi = EDI;
unsigned incr = 2;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time.
*/
@ -563,7 +563,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW32_DXXw(bxInstruction_c *i)
Bit32u esi = ESI;
unsigned incr = 2;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time.
*/

View File

@ -28,7 +28,7 @@
// Repeat Speedups methods
//
#if BX_SupportRepeatSpeedups
#if BX_SUPPORT_REPEAT_SPEEDUPS
Bit32u BX_CPU_C::FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count)
{
Bit32u bytesFitSrc, bytesFitDst;
@ -518,7 +518,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB32_XbYb(bxInstruction_c *i)
Bit32u incr = 1;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time */
if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
@ -696,7 +696,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD32_XdYd(bxInstruction_c *i)
Bit32u esi = ESI;
Bit32u edi = EDI;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time.
*/
@ -1663,7 +1663,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB32_YbAL(bxInstruction_c *i)
Bit32u incr = 1;
Bit32u edi = EDI;
#if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
/* If conditions are right, we can transfer IO to physical memory
* in a batch, rather than one instruction at a time.
*/

View File

@ -1086,8 +1086,9 @@ void bx_init_hardware()
}
BX_INFO(("Optimization configuration"));
BX_INFO((" RepeatSpeedups support: %s", BX_SupportRepeatSpeedups?"yes":"no"));
BX_INFO((" RepeatSpeedups support: %s", BX_SUPPORT_REPEAT_SPEEDUPS?"yes":"no"));
BX_INFO((" Fast function calls: %s", BX_FAST_FUNC_CALL?"yes":"no"));
BX_INFO((" Handlers Chaining speedups: %s", BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS?"yes":"no"));
BX_INFO(("Devices configuration"));
BX_INFO((" NE2000 support: %s", BX_SUPPORT_NE2K?"yes":"no"));
BX_INFO((" PCI support: %s, enabled=%s", BX_SUPPORT_PCI?"yes":"no",