aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/opcode/ChangeLog4
-rw-r--r--include/opcode/rx.h3
-rw-r--r--sim/rx/ChangeLog27
-rw-r--r--sim/rx/README.txt121
-rw-r--r--sim/rx/config.in6
-rwxr-xr-xsim/rx/configure1891
-rw-r--r--sim/rx/configure.in30
-rw-r--r--sim/rx/cpu.h19
-rw-r--r--sim/rx/main.c2
-rw-r--r--sim/rx/mem.c156
-rw-r--r--sim/rx/mem.h15
-rw-r--r--sim/rx/reg.c6
-rw-r--r--sim/rx/rx.c825
-rw-r--r--sim/rx/trace.c9
14 files changed, 2365 insertions, 749 deletions
diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog
index f2e1345..a49c207 100644
--- a/include/opcode/ChangeLog
+++ b/include/opcode/ChangeLog
@@ -1,3 +1,7 @@
+2010-07-27 DJ Delorie <dj@redhat.com>
+
+ * rx.h (RX_Opcode_ID): Add nop2 and nop3 for statistics.
+
2010-07-23 Naveen.H.S <naveen.S@kpitcummins.com>
Ina Pandit <ina.pandit@kpitcummins.com>
diff --git a/include/opcode/rx.h b/include/opcode/rx.h
index 54aadf4..0840be0 100644
--- a/include/opcode/rx.h
+++ b/include/opcode/rx.h
@@ -57,7 +57,6 @@ typedef enum
RXO_movbir, /* [s,s2] = d (signed) */
RXO_pushm, /* s..s2 */
RXO_popm, /* s..s2 */
- RXO_pusha, /* &s */
RXO_xchg, /* s <-> d */
RXO_stcc, /* d = s if cond(s2) */
RXO_rtsd, /* rtsd, 1=imm, 2-0 = reg if reg type */
@@ -98,6 +97,8 @@ typedef enum
RXO_jsrrel, /* pc += d */
RXO_rts,
RXO_nop,
+ RXO_nop2,
+ RXO_nop3,
RXO_scmpu,
RXO_smovu,
diff --git a/sim/rx/ChangeLog b/sim/rx/ChangeLog
index 25dc711..ff3c808 100644
--- a/sim/rx/ChangeLog
+++ b/sim/rx/ChangeLog
@@ -1,3 +1,30 @@
+2010-07-27 DJ Delorie <dj@redhat.com>
+
+ * README.txt: New.
+ * config.h (CYCLE_ACCURATE, CYCLE_STATS): New.
+ * configure.in (--enable-cycle-accurate, --enable-cycle-stats):
+ New. Default to enabled.
+ * configure: Regenerate.
+
+ * cpu.h (regs_type): Add cycle tracking info.
+ (reset_pipeline_stats): Declare.
+ (halt_pipeline_stats): Declare.
+ (pipeline_stats): Declare.
+ * main.c (done): Call pipeline_stats().
+ * mem.h (rx_mem_ptr): Moved to here ...
+ * mem.c (mem_ptr): ... from here. Rename throughout.
+ (mem_put_byte): Move LEDs to Port A. Add Port B to control cycle
+ statistics. Move UART to SCI4.
+ (mem_put_hi): Add TPU 1-2. TPU 1 and 2 count CPU cycles.
+ * reg.c (init_regs): Set Rt reg to -1 (no reg).
+ * rx.c: Add cycle counting and statistics throughout.
+ (rx_get_byte): Optimize for speed.
+ (decode_opcode): Likewise.
+ (reset_pipeline_stats): New.
+ (halt_pipeline_stats): New.
+ (pipeline_stats): New.
+ * trace.c (sim_disasm_one): Print cycle count.
+
2010-07-07 Kevin Buettner <kevinb@redhat.com>
* gdb-if.c (sim_store_register): Add case for sim_rx_acc_regnum.
diff --git a/sim/rx/README.txt b/sim/rx/README.txt
new file mode 100644
index 0000000..496e6a1
--- /dev/null
+++ b/sim/rx/README.txt
@@ -0,0 +1,121 @@
+The RX simulator offers two rx-specific configure options:
+
+--enable-cycle-accurate (default)
+--disable-cycle-accurate
+
+If enabled, the simulator will keep track of how many cycles each
+instruction takes. While not 100% accurate, it is very close,
+including modelling fetch stalls and register latency.
+
+--enable-cycle-stats (default)
+--disable-cycle-stats
+
+If enabled, specifying "-v" twice on the simulator command line causes
+the simulator to print statistics on how much time was used by each
+type of opcode, and what pairs of opcodes tend to happen most
+frequently, as well as how many times various pipeline stalls
+happened.
+
+
+
+The RX simulator offers many command line options:
+
+-v - verbose output. This prints some information about where the
+program is being loaded and its starting address, as well as
+information about how much memory was used and how many instructions
+were executed during the run. If specified twice, pipeline and cycle
+information are added to the report.
+
+-d - disassemble output. Each instruction executed is printed.
+
+-t - trace output. Causes a *lot* of printed information about what
+ every instruction is doing, from math results down to register
+ changes.
+
+--ignore-*
+--warn-*
+--error-*
+
+ The RX simulator can detect certain types of memory corruption, and
+ either ignore them, warn the user about them, or error and exit.
+ Note that valid GCC code may trigger some of these, for example,
+ writing a bitfield involves reading the existing value, which may
+ not have been set yet. The options for * are:
+
+ null-deref - memory access to address zero. You must modify your
+ linker script to avoid putting anything at location zero, of
+ course.
+
+ unwritten-pages - attempts to read a page of memory (see below)
+ before it is written. This is much faster than the next option.
+
+ unwritten-bytes - attempts to read individual bytes before they're
+ written.
+
+ corrupt-stack - On return from a subroutine, the memory location
+ where $pc was stored is checked to see if anything other than
+ $pc had been written to it most recently.
+
+-i -w -e - these three options change the settings for all of the
+ above. For example, "-i" tells the simulator to ignore all memory
+ corruption.
+
+-E - end of options. Any remaining options (after the program name)
+ are considered to be options for the simulated program, although
+ such functionality is not supported.
+
+
+
+The RX simulator simulates a small number of peripherals, mostly in
+order to provide I/O capabilities for testing and such. The supported
+peripherals, and their limitations, are documented here.
+
+Memory
+
+Memory for the simulator is stored in a hierarchical tree, much like
+the i386's page directory and page tables. The simulator can allocate
+memory to individual pages as needed, allowing the simulated program
+to act as if it had a full 4 Gb of RAM at its disposal, without
+actually allocating more memory from the host operating system than
+the simulated program actually uses. Note that for each page of
+memory, there's a corresponding page of memory *types* (for tracking
+memory corruption). Memory is initially filled with all zeros.
+
+GPIO Port A
+
+PA.DR is configured as an output-only port (regardless of PA.DDR).
+When written to, a row of colored @ and * symbols are printed,
+reflecting a row of eight LEDs being either on or off.
+
+GPIO Port B
+
+PB.DR controls the pipeline statistics. Writing a 0 to PB.DR disables
+statistics gathering. Writing a non-0 to PB.DR resets all counters
+and enables (even if already enabled) statistics gathering. The
+simulator starts with statistics enabled, so writing to PB.DR is not
+needed if you want statistics on the entire program's run.
+
+SCI4
+
+SCI4.TDR is connected to the simulator's stdout. Any byte written to
+SCI4.TDR is written to stdout. If the simulated program writes the
+bytes 3, 3, and N in sequence, the simulator exits with an exit value
+of N.
+
+SCI4.SSR always returns "transmitter empty".
+
+
+TPU1.TCNT
+TPU2.TCNT
+
+TPU1 and TPU2 are configured as a chained 32-bit counter which counts
+machine cycles. It always runs at "ICLK speed", regardless of the
+clock control settings. Writing to either of these 16-bit registers
+zeros the counter, regardless of the value written. Reading from
+these registers returns the elapsed cycle count, with TPU1 holding the
+most significant word and TPU2 holding the least significant word.
+
+Note that, much like the hardware, these values may (TPU2.CNT *will*)
+change between reads, so you must read TPU1.CNT, then TPU2.CNT, and
+then TPU1.CNT again, and only trust the values if both reads of
+TPU1.CNT were the same.
diff --git a/sim/rx/config.in b/sim/rx/config.in
index f71c45f..7263de3 100644
--- a/sim/rx/config.in
+++ b/sim/rx/config.in
@@ -105,3 +105,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+
+/* --enable-cycle-accurate */
+#undef CYCLE_ACCURATE
+
+/* --enable-cycle-stats */
+#undef CYCLE_STATS
diff --git a/sim/rx/configure b/sim/rx/configure
index 56d03ac..40c4b76 100755
--- a/sim/rx/configure
+++ b/sim/rx/configure
@@ -601,9 +601,6 @@ sim_debug
sim_cflags
sim_bswap
MAINT
-EGREP
-GREP
-CPP
CATOBJEXT
GENCAT
INSTOBJEXT
@@ -623,13 +620,6 @@ CC_FOR_BUILD
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
target_os
target_vendor
target_cpu
@@ -663,6 +653,16 @@ sim_bitsize
sim_assert
sim_alignment
sim_environment
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
target_alias
host_alias
build_alias
@@ -704,6 +704,8 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+enable_cycle_accurate
+enable_cycle_stats
with_zlib
enable_maintainer_mode
enable_sim_bswap
@@ -1342,6 +1344,8 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-cycle-accurate
+ --disable-cycle-stats
--enable-maintainer-mode Enable developer functionality.
--enable-sim-bswap Use Host specific BSWAP instruction.
--enable-sim-cflags=opts Extra CFLAGS for use in building simulator
@@ -2147,6 +2151,1184 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h:config.in"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ rm -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in getopt.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default"
+if test "x$ac_cv_header_getopt_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETOPT_H 1
+_ACEOF
+
+fi
+
+done
+
# This file contains common code used by all simulators.
#
@@ -2192,13 +3374,17 @@ ac_config_headers="$ac_config_headers config.h:config.in"
+# _AC_CHECK_DECL_BODY
+# -------------------
+# Shell function body for AC_CHECK_DECL.
+# _AC_CHECK_DECL_BODY
-
-
-
-
-
-
+# _AC_CHECK_DECLS(SYMBOL, ACTION-IF_FOUND, ACTION-IF-NOT-FOUND,
+# INCLUDES)
+# -------------------------------------------------------------
+# Helper to AC_CHECK_DECLS, which generates the check for a single
+# SYMBOL with INCLUDES, performs the AC_DEFINE, then expands
+# ACTION-IF-FOUND or ACTION-IF-NOT-FOUND.
@@ -2415,6 +3601,42 @@ sim_inline="-DDEFAULT_INLINE=0"
+# Check whether --enable-cycle-accurate was given.
+if test "${enable_cycle_accurate+set}" = set; then :
+ enableval=$enable_cycle_accurate; case "${enableval}" in
+yes | no) ;;
+*) as_fn_error "bad value ${enableval} given for --enable-cycle-accurate option" "$LINENO" 5 ;;
+esac
+fi
+
+
+# Check whether --enable-cycle-stats was given.
+if test "${enable_cycle_stats+set}" = set; then :
+ enableval=$enable_cycle_stats; case "${enableval}" in
+yes | no) ;;
+*) as_fn_error "bad value ${enableval} given for --enable-cycle-stats option" "$LINENO" 5 ;;
+esac
+fi
+
+
+echo enable_cycle_accurate is $enable_cycle_accurate
+echo enable_cycle_stats is $enable_cycle_stats
+
+if test "x${enable_cycle_accurate}" != xno; then
+$as_echo "#define CYCLE_ACCURATE 1" >>confdefs.h
+
+
+ if test "x${enable_cycle_stats}" != xno; then
+ $as_echo "#define CYCLE_STATS 1" >>confdefs.h
+
+ fi
+else
+ if test "x${enable_cycle_stats}" != xno; then
+ as_fn_error "cycle-stats not available without cycle-accurate" "$LINENO" 5
+ fi
+fi
+
+
# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
# it by inlining the macro's contents.
# This file contains common code used by all simulators.
@@ -2908,231 +4130,6 @@ $as_echo "$ac_try_echo"; } >&5
test $ac_status = 0; }
done
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-
-# The possible output files:
-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
-
-ac_rmfiles=
-for ac_file in $ac_files
-do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- * ) ac_rmfiles="$ac_rmfiles $ac_file";;
- esac
-done
-rm -f $ac_rmfiles
-
-if { { ac_try="$ac_link_default"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link_default") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile. We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files ''
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
- then :; else
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- fi
- # We set ac_cv_exeext here because the later test for it is not
- # safe: cross compilers may not add the suffix if given an `-o'
- # argument, so we may need to know it at that point already.
- # Even if this section looks crufty: it has the advantage of
- # actually working.
- break;;
- * )
- break;;
- esac
-done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
-else
- ac_file=''
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-if test -z "$ac_file"; then :
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "C compiler cannot create executables
-See \`config.log' for more details." "$LINENO" 5; }; }
-fi
-ac_exeext=$ac_cv_exeext
-
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." "$LINENO" 5; }
- fi
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
-ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
-if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- break;;
- * ) break;;
- esac
-done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." "$LINENO" 5; }
-fi
-rm -f conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
- for ac_file in conftest.o conftest.obj conftest.*; do
- test -f "$ac_file" || continue;
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." "$LINENO" 5; }
-fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
if test "${ac_cv_c_compiler_gnu+set}" = set; then :
@@ -3619,405 +4616,6 @@ fi
# Check for common headers.
# FIXME: Seems to me this can cause problems for i386-windows hosts.
# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*.
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
for ac_header in stdlib.h string.h strings.h unistd.h time.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -4517,19 +5115,6 @@ sim_link_files="${sim_link_files} ${TARG_VALS_DEF}"
sim_link_links="${sim_link_links} targ-vals.def"
-for ac_header in getopt.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default"
-if test "x$ac_cv_header_getopt_h" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETOPT_H 1
-_ACEOF
-
-fi
-
-done
-
-
ac_sources="$sim_link_files"
ac_dests="$sim_link_links"
diff --git a/sim/rx/configure.in b/sim/rx/configure.in
index 7c51815..653689e 100644
--- a/sim/rx/configure.in
+++ b/sim/rx/configure.in
@@ -25,6 +25,36 @@ AC_CHECK_HEADERS(getopt.h)
sinclude(../common/aclocal.m4)
+AC_ARG_ENABLE(cycle-accurate,
+[ --disable-cycle-accurate ],
+[case "${enableval}" in
+yes | no) ;;
+*) AC_MSG_ERROR(bad value ${enableval} given for --enable-cycle-accurate option) ;;
+esac])
+
+AC_ARG_ENABLE(cycle-stats,
+[ --disable-cycle-stats ],
+[case "${enableval}" in
+yes | no) ;;
+*) AC_MSG_ERROR(bad value ${enableval} given for --enable-cycle-stats option) ;;
+esac])
+
+echo enable_cycle_accurate is $enable_cycle_accurate
+echo enable_cycle_stats is $enable_cycle_stats
+
+if test "x${enable_cycle_accurate}" != xno; then
+AC_DEFINE([CYCLE_ACCURATE])
+
+ if test "x${enable_cycle_stats}" != xno; then
+ AC_DEFINE([CYCLE_STATS])
+ fi
+else
+ if test "x${enable_cycle_stats}" != xno; then
+ AC_ERROR([cycle-stats not available without cycle-accurate])
+ fi
+fi
+
+
# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around
# it by inlining the macro's contents.
sinclude(../common/common.m4)
diff --git a/sim/rx/cpu.h b/sim/rx/cpu.h
index a4afab7..74ab4b6 100644
--- a/sim/rx/cpu.h
+++ b/sim/rx/cpu.h
@@ -76,8 +76,24 @@ typedef struct
SI r_temp;
DI r_acc;
+
+#ifdef CYCLE_ACCURATE
+ /* If set, RTS/RTSD take 2 fewer cycles. */
+ char fast_return;
+ SI link_register;
+
+ unsigned long long cycle_count;
+ /* Bits saying what kind of memory operands the previous insn had. */
+ int m2m;
+ /* Target register for load. */
+ int rt;
+#endif
} regs_type;
+#define M2M_SRC 0x01
+#define M2M_DST 0x02
+#define M2M_BOTH 0x03
+
#define sp 0
#define psw 16
#define pc 17
@@ -219,6 +235,9 @@ extern unsigned int heaptop;
extern unsigned int heapbottom;
extern int decode_opcode (void);
+extern void reset_pipeline_stats (void);
+extern void halt_pipeline_stats (void);
+extern void pipeline_stats (void);
extern void trace_register_changes ();
extern void generate_access_exception (void);
diff --git a/sim/rx/main.c b/sim/rx/main.c
index a83794e..27ff0b8 100644
--- a/sim/rx/main.c
+++ b/sim/rx/main.c
@@ -82,6 +82,8 @@ done (int exit_code)
printf ("insns: %14s\n", comma (rx_cycles));
else
printf ("insns: %u\n", rx_cycles);
+
+ pipeline_stats ();
}
exit (exit_code);
}
diff --git a/sim/rx/mem.c b/sim/rx/mem.c
index 5556ea0..3b7a7a2 100644
--- a/sim/rx/mem.c
+++ b/sim/rx/mem.c
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
1. */
#define RDCHECK 0
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -37,7 +38,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#define L1_BITS (10)
#define L2_BITS (10)
-#define OFF_BITS (12)
+#define OFF_BITS PAGE_BITS
#define L1_LEN (1 << L1_BITS)
#define L2_LEN (1 << L2_BITS)
@@ -70,15 +71,8 @@ init_mem (void)
memset (mem_counters, 0, sizeof (mem_counters));
}
-enum mem_ptr_action
-{
- MPA_WRITING,
- MPA_READING,
- MPA_CONTENT_TYPE
-};
-
-static unsigned char *
-mem_ptr (unsigned long address, enum mem_ptr_action action)
+unsigned char *
+rx_mem_ptr (unsigned long address, enum mem_ptr_action action)
{
int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
@@ -240,7 +234,7 @@ e ()
static char
mtypec (int address)
{
- unsigned char *cp = mem_ptr (address, MPA_CONTENT_TYPE);
+ unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE);
return "udp"[*cp];
}
@@ -254,48 +248,75 @@ mem_put_byte (unsigned int address, unsigned char value)
if (trace)
tc = mtypec (address);
- m = mem_ptr (address, MPA_WRITING);
+ m = rx_mem_ptr (address, MPA_WRITING);
if (trace)
printf (" %02x%c", value, tc);
*m = value;
switch (address)
{
- case 0x00e1:
- {
+ case 0x0008c02a: /* PA.DR */
+ {
static int old_led = -1;
- static char *led_on[] =
- { "\033[31m O ", "\033[32m O ", "\033[34m O " };
- static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " };
+ int red_on = 0;
int i;
+
if (old_led != value)
{
- fputs (" ", stdout);
- for (i = 0; i < 3; i++)
+ fputs (" ", stdout);
+ for (i = 0; i < 8; i++)
if (value & (1 << i))
- fputs (led_off[i], stdout);
+ {
+ if (! red_on)
+ {
+ fputs ("\033[31m", stdout);
+ red_on = 1;
+ }
+ fputs (" @", stdout);
+ }
else
- fputs (led_on[i], stdout);
- fputs ("\033[0m\r", stdout);
+ {
+ if (red_on)
+ {
+ fputs ("\033[0m", stdout);
+ red_on = 0;
+ }
+ fputs (" *", stdout);
+ }
+
+ if (red_on)
+ fputs ("\033[0m", stdout);
+
+ fputs ("\r", stdout);
fflush (stdout);
old_led = value;
}
}
break;
- case 0x3aa: /* uart1tx */
+#ifdef CYCLE_STATS
+ case 0x0008c02b: /* PB.DR */
{
- static int pending_exit = 0;
if (value == 0)
+ halt_pipeline_stats ();
+ else
+ reset_pipeline_stats ();
+ }
+#endif
+
+ case 0x00088263: /* SCI4.TDR */
+ {
+ static int pending_exit = 0;
+ if (pending_exit == 2)
{
- if (pending_exit)
- {
- step_result = RX_MAKE_EXITED(value);
- return;
- }
- pending_exit = 1;
+ step_result = RX_MAKE_EXITED(value);
+ longjmp (decode_jmp_buf, 1);
}
+ else if (value == 3)
+ pending_exit ++;
else
- putchar(value);
+ pending_exit = 0;
+
+ putchar(value);
}
break;
@@ -314,19 +335,33 @@ mem_put_qi (int address, unsigned char value)
COUNT (1, 1);
}
+static int tpu_base;
+
void
mem_put_hi (int address, unsigned short value)
{
S ("<=");
- if (rx_big_endian)
- {
- mem_put_byte (address, value >> 8);
- mem_put_byte (address + 1, value & 0xff);
- }
- else
+ switch (address)
{
- mem_put_byte (address, value & 0xff);
- mem_put_byte (address + 1, value >> 8);
+#ifdef CYCLE_ACCURATE
+ case 0x00088126: /* TPU1.TCNT */
+ tpu_base = regs.cycle_count;
+ break;
+ case 0x00088136: /* TPU2.TCNT */
+ tpu_base = regs.cycle_count;
+ break;
+#endif
+ default:
+ if (rx_big_endian)
+ {
+ mem_put_byte (address, value >> 8);
+ mem_put_byte (address + 1, value & 0xff);
+ }
+ else
+ {
+ mem_put_byte (address, value & 0xff);
+ mem_put_byte (address + 1, value >> 8);
+ }
}
E ();
COUNT (1, 2);
@@ -388,7 +423,7 @@ mem_put_blk (int address, void *bufptr, int nbytes)
unsigned char
mem_get_pc (int address)
{
- unsigned char *m = mem_ptr (address, MPA_READING);
+ unsigned char *m = rx_mem_ptr (address, MPA_READING);
COUNT (0, 0);
return *m;
}
@@ -399,12 +434,12 @@ mem_get_byte (unsigned int address)
unsigned char *m;
S ("=>");
- m = mem_ptr (address, MPA_READING);
+ m = rx_mem_ptr (address, MPA_READING);
switch (address)
{
- case 0x3ad: /* uart1c1 */
+ case 0x00088264: /* SCI4.SSR */
E();
- return 2; /* transmitter empty */
+ return 0x04; /* transmitter empty */
break;
default:
if (trace)
@@ -433,15 +468,28 @@ mem_get_hi (int address)
{
unsigned short rv;
S ("=>");
- if (rx_big_endian)
- {
- rv = mem_get_byte (address) << 8;
- rv |= mem_get_byte (address + 1);
- }
- else
+ switch (address)
{
- rv = mem_get_byte (address);
- rv |= mem_get_byte (address + 1) << 8;
+#ifdef CYCLE_ACCURATE
+ case 0x00088126: /* TPU1.TCNT */
+ rv = (regs.cycle_count - tpu_base) >> 16;
+ break;
+ case 0x00088136: /* TPU2.TCNT */
+ rv = (regs.cycle_count - tpu_base) >> 0;
+ break;
+#endif
+
+ default:
+ if (rx_big_endian)
+ {
+ rv = mem_get_byte (address) << 8;
+ rv |= mem_get_byte (address + 1);
+ }
+ else
+ {
+ rv = mem_get_byte (address);
+ rv |= mem_get_byte (address + 1) << 8;
+ }
}
COUNT (0, 2);
E ();
@@ -520,7 +568,7 @@ sign_ext (int v, int bits)
void
mem_set_content_type (int address, enum mem_content_type type)
{
- unsigned char *mt = mem_ptr (address, MPA_CONTENT_TYPE);
+ unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
*mt = type;
}
@@ -537,7 +585,7 @@ mem_set_content_range (int start_address, int end_address, enum mem_content_type
if (sz + ofs > L1_LEN)
sz = L1_LEN - ofs;
- mt = mem_ptr (start_address, MPA_CONTENT_TYPE);
+ mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
memset (mt, type, sz);
start_address += sz;
@@ -547,6 +595,6 @@ mem_set_content_range (int start_address, int end_address, enum mem_content_type
enum mem_content_type
mem_get_content_type (int address)
{
- unsigned char *mt = mem_ptr (address, MPA_CONTENT_TYPE);
+ unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
return *mt;
}
diff --git a/sim/rx/mem.h b/sim/rx/mem.h
index 1b8320a..37740d5 100644
--- a/sim/rx/mem.h
+++ b/sim/rx/mem.h
@@ -25,10 +25,25 @@ enum mem_content_type {
MC_NUM_TYPES
};
+enum mem_ptr_action
+{
+ MPA_WRITING,
+ MPA_READING,
+ MPA_CONTENT_TYPE
+};
+
void init_mem (void);
void mem_usage_stats (void);
unsigned long mem_usage_cycles (void);
+/* rx_mem_ptr returns a pointer which is valid as long as the address
+ requested remains within the same page. */
+#define PAGE_BITS 12
+#define PAGE_SIZE (1 << PAGE_BITS)
+#define NONPAGE_MASK (~(PAGE_SIZE-1))
+
+unsigned char *rx_mem_ptr (unsigned long address, enum mem_ptr_action action);
+
void mem_put_qi (int address, unsigned char value);
void mem_put_hi (int address, unsigned short value);
void mem_put_psi (int address, unsigned long value);
diff --git a/sim/rx/reg.c b/sim/rx/reg.c
index f635b6d..0103d21 100644
--- a/sim/rx/reg.c
+++ b/sim/rx/reg.c
@@ -19,6 +19,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -67,6 +68,11 @@ init_regs (void)
{
memset (&regs, 0, sizeof (regs));
memset (&oldregs, 0, sizeof (oldregs));
+
+#ifdef CYCLE_ACCURATE
+ regs.rt = -1;
+ oldregs.rt = -1;
+#endif
}
static unsigned int
diff --git a/sim/rx/rx.c b/sim/rx/rx.c
index f1ce809..a6503de 100644
--- a/sim/rx/rx.c
+++ b/sim/rx/rx.c
@@ -18,6 +18,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -29,12 +30,253 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "syscalls.h"
#include "fpu.h"
#include "err.h"
+#include "misc.h"
+
+#ifdef CYCLE_STATS
+static const char * id_names[] = {
+ "RXO_unknown",
+ "RXO_mov", /* d = s (signed) */
+ "RXO_movbi", /* d = [s,s2] (signed) */
+ "RXO_movbir", /* [s,s2] = d (signed) */
+ "RXO_pushm", /* s..s2 */
+ "RXO_popm", /* s..s2 */
+ "RXO_xchg", /* s <-> d */
+ "RXO_stcc", /* d = s if cond(s2) */
+ "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
+
+ /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
+ that d may be "None". */
+ "RXO_and",
+ "RXO_or",
+ "RXO_xor",
+ "RXO_add",
+ "RXO_sub",
+ "RXO_mul",
+ "RXO_div",
+ "RXO_divu",
+ "RXO_shll",
+ "RXO_shar",
+ "RXO_shlr",
+
+ "RXO_adc", /* d = d + s + carry */
+ "RXO_sbb", /* d = d - s - ~carry */
+ "RXO_abs", /* d = |s| */
+ "RXO_max", /* d = max(d,s) */
+ "RXO_min", /* d = min(d,s) */
+ "RXO_emul", /* d:64 = d:32 * s */
+ "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
+ "RXO_ediv", /* d:64 / s; d = quot, d+1 = rem */
+ "RXO_edivu", /* d:64 / s; d = quot, d+1 = rem */
+
+ "RXO_rolc", /* d <<= 1 through carry */
+ "RXO_rorc", /* d >>= 1 through carry*/
+ "RXO_rotl", /* d <<= #s without carry */
+ "RXO_rotr", /* d >>= #s without carry*/
+ "RXO_revw", /* d = revw(s) */
+ "RXO_revl", /* d = revl(s) */
+ "RXO_branch", /* pc = d if cond(s) */
+ "RXO_branchrel",/* pc += d if cond(s) */
+ "RXO_jsr", /* pc = d */
+ "RXO_jsrrel", /* pc += d */
+ "RXO_rts",
+ "RXO_nop",
+ "RXO_nop2",
+ "RXO_nop3",
+
+ "RXO_scmpu",
+ "RXO_smovu",
+ "RXO_smovb",
+ "RXO_suntil",
+ "RXO_swhile",
+ "RXO_smovf",
+ "RXO_sstr",
+
+ "RXO_rmpa",
+ "RXO_mulhi",
+ "RXO_mullo",
+ "RXO_machi",
+ "RXO_maclo",
+ "RXO_mvtachi",
+ "RXO_mvtaclo",
+ "RXO_mvfachi",
+ "RXO_mvfacmi",
+ "RXO_mvfaclo",
+ "RXO_racw",
+
+ "RXO_sat", /* sat(d) */
+ "RXO_satr",
+
+ "RXO_fadd", /* d op= s */
+ "RXO_fcmp",
+ "RXO_fsub",
+ "RXO_ftoi",
+ "RXO_fmul",
+ "RXO_fdiv",
+ "RXO_round",
+ "RXO_itof",
+
+ "RXO_bset", /* d |= (1<<s) */
+ "RXO_bclr", /* d &= ~(1<<s) */
+ "RXO_btst", /* s & (1<<s2) */
+ "RXO_bnot", /* d ^= (1<<s) */
+ "RXO_bmcc", /* d<s> = cond(s2) */
+
+ "RXO_clrpsw", /* flag index in d */
+ "RXO_setpsw", /* flag index in d */
+ "RXO_mvtipl", /* new IPL in s */
+
+ "RXO_rtfi",
+ "RXO_rte",
+ "RXO_rtd", /* undocumented */
+ "RXO_brk",
+ "RXO_dbt", /* undocumented */
+ "RXO_int", /* vector id in s */
+ "RXO_stop",
+ "RXO_wait",
+
+ "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
+};
+
+static const char * optype_names[] = {
+ " ",
+ "#Imm", /* #addend */
+ " Rn ", /* Rn */
+ "[Rn]", /* [Rn + addend] */
+ "Ps++", /* [Rn+] */
+ "--Pr", /* [-Rn] */
+ " cc ", /* eq, gtu, etc */
+ "Flag" /* [UIOSZC] */
+};
+
+#define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
+#define N_RXT (sizeof(optype_names)/sizeof(optype_names[0]))
+#define N_MAP 30
+
+static unsigned long long benchmark_start_cycle;
+static unsigned long long benchmark_end_cycle;
+
+static int op_cache[N_RXT][N_RXT][N_RXT];
+static int op_cache_rev[N_MAP];
+static int op_cache_idx = 0;
+
+static int
+op_lookup (int a, int b, int c)
+{
+ if (op_cache[a][b][c])
+ return op_cache[a][b][c];
+ op_cache_idx ++;
+ if (op_cache_idx >= N_MAP)
+ {
+ printf("op_cache_idx exceeds %d\n", N_MAP);
+ exit(1);
+ }
+ op_cache[a][b][c] = op_cache_idx;
+ op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
+ return op_cache_idx;
+}
+
+static char *
+op_cache_string (int map)
+{
+ static int ci;
+ static char cb[5][20];
+ int a, b, c;
+
+ map = op_cache_rev[map];
+ a = (map >> 8) & 15;
+ b = (map >> 4) & 15;
+ c = (map >> 0) & 15;
+ ci = (ci + 1) % 5;
+ sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
+ return cb[ci];
+}
+
+static unsigned long long cycles_per_id[N_RXO][N_MAP];
+static unsigned long long times_per_id[N_RXO][N_MAP];
+static unsigned long long memory_stalls;
+static unsigned long long register_stalls;
+static unsigned long long branch_stalls;
+static unsigned long long branch_alignment_stalls;
+static unsigned long long fast_returns;
+
+static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
+static int prev_opcode_id = RXO_unknown;
+static int po0;
+
+#define STATS(x) x
+
+#else
+#define STATS(x)
+#endif /* CYCLE_STATS */
+
+
+#ifdef CYCLE_ACCURATE
+
+static int new_rt = -1;
+
+/* Number of cycles to add if an insn spans an 8-byte boundary. */
+static int branch_alignment_penalty = 0;
-#define tprintf if (trace) printf
+#endif
+
+static int running_benchmark = 1;
+
+#define tprintf if (trace && running_benchmark) printf
jmp_buf decode_jmp_buf;
unsigned int rx_cycles = 0;
+#ifdef CYCLE_ACCURATE
+/* If nonzero, memory was read at some point and cycle latency might
+ take effect. */
+static int memory_source = 0;
+/* If nonzero, memory was written and extra cycles might be
+ needed. */
+static int memory_dest = 0;
+
+static void
+cycles (int throughput)
+{
+ tprintf("%d cycles\n", throughput);
+ regs.cycle_count += throughput;
+}
+
+/* Number of execution (E) cycles the op uses. For memory sources, we
+ include the load micro-op stall as two extra E cycles. */
+#define E(c) cycles (memory_source ? c + 2 : c)
+#define E1 cycles (1)
+#define E2 cycles (2)
+#define EBIT cycles (memory_source ? 2 : 1)
+
+/* Check to see if a read latency must be applied for a given register. */
+#define RL(r) \
+ if (regs.rt == r ) \
+ { \
+ tprintf("register %d load stall\n", r); \
+ regs.cycle_count ++; \
+ STATS(register_stalls ++); \
+ regs.rt = -1; \
+ }
+
+#define RLD(r) \
+ if (memory_source) \
+ { \
+ tprintf ("Rt now %d\n", r); \
+ new_rt = r; \
+ }
+
+#else /* !CYCLE_ACCURATE */
+
+#define cycles(t)
+#define E(c)
+#define E1
+#define E2
+#define EBIT
+#define RL(r)
+#define RLD(r)
+
+#endif /* else CYCLE_ACCURATE */
+
static int size2bytes[] = {
4, 1, 1, 1, 2, 2, 2, 3, 4
};
@@ -53,24 +295,28 @@ _rx_abort (const char *file, int line)
abort();
}
+static unsigned char *get_byte_base;
+static SI get_byte_page;
+
+/* This gets called a *lot* so optimize it. */
static int
rx_get_byte (void *vdata)
{
- int saved_trace = trace;
- unsigned char rv;
-
- if (trace == 1)
- trace = 0;
-
RX_Data *rx_data = (RX_Data *)vdata;
+ SI tpc = rx_data->dpc;
+
+ /* See load.c for an explanation of this. */
if (rx_big_endian)
- /* See load.c for an explanation of this. */
- rv = mem_get_pc (rx_data->dpc ^ 3);
- else
- rv = mem_get_pc (rx_data->dpc);
+ tpc ^= 3;
+
+ if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
+ {
+ get_byte_page = tpc & NONPAGE_MASK;
+ get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
+ }
+
rx_data->dpc ++;
- trace = saved_trace;
- return rv;
+ return get_byte_base [tpc];
}
static int
@@ -88,6 +334,7 @@ get_op (RX_Opcode_Decoded *rd, int i)
return o->addend;
case RX_Operand_Register: /* Rn */
+ RL (o->reg);
rv = get_reg (o->reg);
break;
@@ -96,6 +343,21 @@ get_op (RX_Opcode_Decoded *rd, int i)
/* fall through */
case RX_Operand_Postinc: /* [Rn+] */
case RX_Operand_Indirect: /* [Rn + addend] */
+#ifdef CYCLE_ACCURATE
+ RL (o->reg);
+ regs.rt = -1;
+ if (regs.m2m == M2M_BOTH)
+ {
+ tprintf("src memory stall\n");
+#ifdef CYCLE_STATS
+ memory_stalls ++;
+#endif
+ regs.cycle_count ++;
+ regs.m2m = 0;
+ }
+
+ memory_source = 1;
+#endif
addr = get_reg (o->reg) + o->addend;
switch (o->size)
@@ -234,6 +496,7 @@ put_op (RX_Opcode_Decoded *rd, int i, int v)
case RX_Operand_Register: /* Rn */
put_reg (o->reg, v);
+ RLD (o->reg);
break;
case RX_Operand_Predec: /* [-Rn] */
@@ -242,6 +505,19 @@ put_op (RX_Opcode_Decoded *rd, int i, int v)
case RX_Operand_Postinc: /* [Rn+] */
case RX_Operand_Indirect: /* [Rn + addend] */
+#ifdef CYCLE_ACCURATE
+ if (regs.m2m == M2M_BOTH)
+ {
+ tprintf("dst memory stall\n");
+ regs.cycle_count ++;
+#ifdef CYCLE_STATS
+ memory_stalls ++;
+#endif
+ regs.m2m = 0;
+ }
+ memory_dest = 1;
+#endif
+
addr = get_reg (o->reg) + o->addend;
switch (o->size)
{
@@ -345,8 +621,8 @@ poppc()
#define MATH_OP(vop,c) \
{ \
- uma = US1(); \
umb = US2(); \
+ uma = US1(); \
ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
ma = sign_ext (uma, DSZ() * 8); \
@@ -355,23 +631,25 @@ poppc()
tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
PD (sll); \
+ E (1); \
}
#define LOGIC_OP(vop) \
{ \
- ma = US1(); \
mb = US2(); \
+ ma = US1(); \
v = ma vop mb; \
tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
set_sz (v, DSZ()); \
PD(v); \
+ E (1); \
}
#define SHIFT_OP(val, type, count, OP, carry_mask) \
{ \
int i, c=0; \
- val = (type)US1(); \
count = US2(); \
+ val = (type)US1(); \
tprintf("%lld " #OP " %d\n", val, count); \
for (i = 0; i < count; i ++) \
{ \
@@ -443,8 +721,8 @@ fop_fsub (fp_t s1, fp_t s2, fp_t *d)
int do_store; \
fp_t fa, fb, fc; \
FPCLEAR(); \
- fa = GD (); \
fb = GS (); \
+ fa = GD (); \
do_store = fop_##func (fa, fb, &fc); \
tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
FPCHECK(); \
@@ -549,6 +827,21 @@ do_fp_exception (unsigned long opcode_pc)
return RX_MAKE_STEPPED ();
}
+static int
+op_is_memory (RX_Opcode_Decoded *rd, int i)
+{
+ switch (rd->op[i].type)
+ {
+ case RX_Operand_Predec:
+ case RX_Operand_Postinc:
+ case RX_Operand_Indirect:
+ return 1;
+ default:
+ return 0;
+ }
+}
+#define OM(i) op_is_memory (&opcode, i)
+
int
decode_opcode ()
{
@@ -561,14 +854,46 @@ decode_opcode ()
RX_Data rx_data;
RX_Opcode_Decoded opcode;
int rv;
+#ifdef CYCLE_STATS
+ unsigned long long prev_cycle_count;
+#endif
+#ifdef CYCLE_ACCURATE
+ int tx;
+#endif
if ((rv = setjmp (decode_jmp_buf)))
return rv;
+#ifdef CYCLE_STATS
+ prev_cycle_count = regs.cycle_count;
+#endif
+
+#ifdef CYCLE_ACCURATE
+ memory_source = 0;
+ memory_dest = 0;
+#endif
+
rx_cycles ++;
rx_data.dpc = opcode_pc = regs.r_pc;
+ memset (&opcode, 0, sizeof(opcode));
opcode_size = rx_decode_opcode (opcode_pc, &opcode, rx_get_byte, &rx_data);
+
+#ifdef CYCLE_ACCURATE
+ if (branch_alignment_penalty)
+ {
+ if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
+ {
+ tprintf("1 cycle branch alignment penalty\n");
+ cycles (branch_alignment_penalty);
+#ifdef CYCLE_STATS
+ branch_alignment_stalls ++;
+#endif
+ }
+ branch_alignment_penalty = 0;
+ }
+#endif
+
regs.r_pc += opcode_size;
rx_flagmask = opcode.flags_s;
@@ -585,6 +910,7 @@ decode_opcode ()
tprintf("%lld\n", sll);
PD (sll);
set_osz (sll, 4);
+ E (1);
break;
case RXO_adc:
@@ -608,6 +934,7 @@ decode_opcode ()
mb &= 0x07;
ma &= ~(1 << mb);
PD (ma);
+ EBIT;
break;
case RXO_bmcc:
@@ -622,6 +949,7 @@ decode_opcode ()
else
ma &= ~(1 << mb);
PD (ma);
+ EBIT;
break;
case RXO_bnot:
@@ -633,16 +961,71 @@ decode_opcode ()
mb &= 0x07;
ma ^= (1 << mb);
PD (ma);
+ EBIT;
break;
case RXO_branch:
if (GS())
- regs.r_pc = GD();
+ {
+#ifdef CYCLE_ACCURATE
+ SI old_pc = regs.r_pc;
+ int delta;
+#endif
+ regs.r_pc = GD();
+#ifdef CYCLE_ACCURATE
+ delta = regs.r_pc - old_pc;
+ if (delta >= 0 && delta < 16
+ && opcode_size > 1)
+ {
+ tprintf("near forward branch bonus\n");
+ cycles (2);
+ }
+ else
+ {
+ cycles (3);
+ branch_alignment_penalty = 1;
+ }
+#ifdef CYCLE_STATS
+ branch_stalls ++;
+ /* This is just for statistics */
+ if (opcode.op[1].reg == 14)
+ opcode.op[1].type = RX_Operand_None;
+#endif
+#endif
+ }
+#ifdef CYCLE_ACCURATE
+ else
+ cycles (1);
+#endif
break;
case RXO_branchrel:
if (GS())
- regs.r_pc += GD();
+ {
+ int delta = GD();
+ regs.r_pc += delta;
+#ifdef CYCLE_ACCURATE
+ /* Note: specs say 3, chip says 2. */
+ if (delta >= 0 && delta < 16
+ && opcode_size > 1)
+ {
+ tprintf("near forward branch bonus\n");
+ cycles (2);
+ }
+ else
+ {
+ cycles (3);
+ branch_alignment_penalty = 1;
+ }
+#ifdef CYCLE_STATS
+ branch_stalls ++;
+#endif
+#endif
+ }
+#ifdef CYCLE_ACCURATE
+ else
+ cycles (1);
+#endif
break;
case RXO_brk:
@@ -659,6 +1042,7 @@ decode_opcode ()
pushpc (old_psw);
pushpc (regs.r_pc);
regs.r_pc = mem_get_si (regs.r_intb);
+ cycles(6);
}
break;
@@ -671,6 +1055,7 @@ decode_opcode ()
mb &= 0x07;
ma |= (1 << mb);
PD (ma);
+ EBIT;
break;
case RXO_btst:
@@ -682,6 +1067,7 @@ decode_opcode ()
mb &= 0x07;
umb = ma & (1 << mb);
set_zc (! umb, umb);
+ EBIT;
break;
case RXO_clrpsw:
@@ -691,6 +1077,7 @@ decode_opcode ()
|| v == FLAGBIT_U))
break;
regs.r_psw &= ~v;
+ cycles (1);
break;
case RXO_div: /* d = d / s */
@@ -709,6 +1096,8 @@ decode_opcode ()
set_flags (FLAGBIT_O, 0);
PD (v);
}
+ /* Note: spec says 3 to 22 cycles, we are pessimistic. */
+ cycles (22);
break;
case RXO_divu: /* d = d / s */
@@ -727,6 +1116,8 @@ decode_opcode ()
set_flags (FLAGBIT_O, 0);
PD (v);
}
+ /* Note: spec says 2 to 20 cycles, we are pessimistic. */
+ cycles (20);
break;
case RXO_ediv:
@@ -748,6 +1139,8 @@ decode_opcode ()
opcode.op[0].reg ++;
PD (mb);
}
+ /* Note: spec says 3 to 22 cycles, we are pessimistic. */
+ cycles (22);
break;
case RXO_edivu:
@@ -769,6 +1162,8 @@ decode_opcode ()
opcode.op[0].reg ++;
PD (umb);
}
+ /* Note: spec says 2 to 20 cycles, we are pessimistic. */
+ cycles (20);
break;
case RXO_emul:
@@ -779,6 +1174,7 @@ decode_opcode ()
PD (sll);
opcode.op[0].reg ++;
PD (sll >> 32);
+ E2;
break;
case RXO_emulu:
@@ -789,10 +1185,12 @@ decode_opcode ()
PD (ll);
opcode.op[0].reg ++;
PD (ll >> 32);
+ E2;
break;
case RXO_fadd:
FLOAT_OP (fadd);
+ E (4);
break;
case RXO_fcmp:
@@ -801,24 +1199,32 @@ decode_opcode ()
FPCLEAR ();
rxfp_cmp (ma, mb);
FPCHECK ();
+ E (1);
break;
case RXO_fdiv:
FLOAT_OP (fdiv);
+ E (16);
break;
case RXO_fmul:
FLOAT_OP (fmul);
+ E (3);
break;
case RXO_rtfi:
PRIVILEDGED ();
regs.r_psw = regs.r_bpsw;
regs.r_pc = regs.r_bpc;
+#ifdef CYCLE_ACCURATE
+ regs.fast_return = 0;
+ cycles(3);
+#endif
break;
case RXO_fsub:
FLOAT_OP (fsub);
+ E (4);
break;
case RXO_ftoi:
@@ -829,6 +1235,7 @@ decode_opcode ()
PD (mb);
tprintf("(int) %g = %d\n", int2float(ma), mb);
set_sz (mb, 4);
+ E (2);
break;
case RXO_int:
@@ -845,6 +1252,7 @@ decode_opcode ()
pushpc (regs.r_pc);
regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
}
+ cycles (6);
break;
case RXO_itof:
@@ -855,49 +1263,87 @@ decode_opcode ()
tprintf("(float) %d = %x\n", ma, mb);
PD (mb);
set_sz (ma, 4);
+ E (2);
break;
case RXO_jsr:
case RXO_jsrrel:
- v = GD ();
- pushpc (get_reg (pc));
- if (opcode.id == RXO_jsrrel)
- v += regs.r_pc;
- put_reg (pc, v);
+ {
+#ifdef CYCLE_ACCURATE
+ int delta;
+ regs.m2m = 0;
+#endif
+ v = GD ();
+#ifdef CYCLE_ACCURATE
+ regs.link_register = regs.r_pc;
+#endif
+ pushpc (get_reg (pc));
+ if (opcode.id == RXO_jsrrel)
+ v += regs.r_pc;
+#ifdef CYCLE_ACCURATE
+ delta = v - regs.r_pc;
+#endif
+ put_reg (pc, v);
+#ifdef CYCLE_ACCURATE
+ /* Note: docs say 3, chip says 2 */
+ if (delta >= 0 && delta < 16)
+ {
+ tprintf ("near forward jsr bonus\n");
+ cycles (2);
+ }
+ else
+ {
+ branch_alignment_penalty = 1;
+ cycles (3);
+ }
+ regs.fast_return = 1;
+#endif
+ }
break;
case RXO_machi:
ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
ll <<= 16;
put_reg64 (acc64, ll + regs.r_acc);
+ E1;
break;
case RXO_maclo:
ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
ll <<= 16;
put_reg64 (acc64, ll + regs.r_acc);
+ E1;
break;
case RXO_max:
- ma = GD();
mb = GS();
+ ma = GD();
if (ma > mb)
PD (ma);
else
PD (mb);
+ E (1);
+#ifdef CYCLE_STATS
+ if (opcode.op[0].type == RX_Operand_Register
+ && opcode.op[1].type == RX_Operand_Register
+ && opcode.op[0].reg == opcode.op[1].reg)
+ opcode.id = RXO_nop3;
+#endif
break;
case RXO_min:
- ma = GD();
mb = GS();
+ ma = GD();
if (ma < mb)
PD (ma);
else
PD (mb);
+ E (1);
break;
case RXO_mov:
v = GS ();
+
if (opcode.op[0].type == RX_Operand_Register
&& opcode.op[0].reg == 16 /* PSW */)
{
@@ -927,8 +1373,32 @@ decode_opcode ()
/* These are ignored. */
break;
}
+ if (OM(0) && OM(1))
+ cycles (2);
+ else
+ cycles (1);
+
PD (v);
+
+#ifdef CYCLE_ACCURATE
+ if ((opcode.op[0].type == RX_Operand_Predec
+ && opcode.op[1].type == RX_Operand_Register)
+ || (opcode.op[0].type == RX_Operand_Postinc
+ && opcode.op[1].type == RX_Operand_Register))
+ {
+ /* Special case: push reg doesn't cause a memory stall. */
+ memory_dest = 0;
+ tprintf("push special case\n");
+ }
+#endif
+
set_sz (v, DSZ());
+#ifdef CYCLE_STATS
+ if (opcode.op[0].type == RX_Operand_Register
+ && opcode.op[1].type == RX_Operand_Register
+ && opcode.op[0].reg == opcode.op[1].reg)
+ opcode.id = RXO_nop2;
+#endif
break;
case RXO_movbi:
@@ -939,6 +1409,7 @@ decode_opcode ()
opcode.op[1].type = RX_Operand_Indirect;
opcode.op[1].addend = 0;
PD (GS ());
+ cycles (1);
break;
case RXO_movbir:
@@ -949,51 +1420,65 @@ decode_opcode ()
opcode.op[1].type = RX_Operand_Indirect;
opcode.op[1].addend = 0;
PS (GD ());
+ cycles (1);
break;
case RXO_mul:
- ll = (unsigned long long) US1() * (unsigned long long) US2();
+ v = US2 ();
+ ll = (unsigned long long) US1() * (unsigned long long) v;
PD(ll);
+ E (1);
break;
case RXO_mulhi:
- ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
+ v = GS2 ();
+ ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
ll <<= 16;
put_reg64 (acc64, ll);
+ E1;
break;
case RXO_mullo:
- ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
+ v = GS2 ();
+ ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
ll <<= 16;
put_reg64 (acc64, ll);
+ E1;
break;
case RXO_mvfachi:
PD (get_reg (acchi));
+ E1;
break;
case RXO_mvfaclo:
PD (get_reg (acclo));
+ E1;
break;
case RXO_mvfacmi:
PD (get_reg (accmi));
+ E1;
break;
case RXO_mvtachi:
put_reg (acchi, GS ());
+ E1;
break;
case RXO_mvtaclo:
put_reg (acclo, GS ());
+ E1;
break;
case RXO_mvtipl:
regs.r_psw &= ~ FLAGBITS_IPL;
regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
+ E1;
break;
case RXO_nop:
+ E1;
break;
case RXO_or:
@@ -1010,11 +1495,11 @@ decode_opcode ()
return RX_MAKE_STOPPED (SIGILL);
}
for (v = opcode.op[1].reg; v <= opcode.op[2].reg; v++)
- put_reg (v, pop ());
- break;
-
- case RXO_pusha:
- push (get_reg (opcode.op[1].reg) + opcode.op[1].addend);
+ {
+ cycles (1);
+ RLD (v);
+ put_reg (v, pop ());
+ }
break;
case RXO_pushm:
@@ -1027,7 +1512,11 @@ decode_opcode ()
return RX_MAKE_STOPPED (SIGILL);
}
for (v = opcode.op[2].reg; v >= opcode.op[1].reg; v--)
- push (get_reg (v));
+ {
+ RL (v);
+ push (get_reg (v));
+ }
+ cycles (opcode.op[2].reg - opcode.op[1].reg + 1);
break;
case RXO_racw:
@@ -1040,6 +1529,7 @@ decode_opcode ()
else
ll &= 0xffffffff00000000ULL;
put_reg64 (acc64, ll);
+ E1;
break;
case RXO_rte:
@@ -1048,6 +1538,10 @@ decode_opcode ()
regs.r_psw = poppc ();
if (FLAG_PM)
regs.r_psw |= FLAGBIT_U;
+#ifdef CYCLE_ACCURATE
+ regs.fast_return = 0;
+ cycles (6);
+#endif
break;
case RXO_revl:
@@ -1057,6 +1551,7 @@ decode_opcode ()
| ((uma << 8) & 0xff0000)
| ((uma << 24) & 0xff000000UL));
PD (umb);
+ E1;
break;
case RXO_revw:
@@ -1064,9 +1559,16 @@ decode_opcode ()
umb = (((uma >> 8) & 0x00ff00ff)
| ((uma << 8) & 0xff00ff00UL));
PD (umb);
+ E1;
break;
case RXO_rmpa:
+ RL(4);
+ RL(5);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
+
while (regs.r[3] != 0)
{
long long tmp;
@@ -1124,6 +1626,22 @@ decode_opcode ()
set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
else
set_flags (FLAGBIT_O|FLAGBIT_S, ma);
+#ifdef CYCLE_ACCURATE
+ switch (opcode.size)
+ {
+ case RX_Long:
+ cycles (6 + 4 * tx);
+ break;
+ case RX_Word:
+ cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
+ break;
+ case RX_Byte:
+ cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
+ break;
+ default:
+ abort ();
+ }
+#endif
break;
case RXO_rolc:
@@ -1133,6 +1651,7 @@ decode_opcode ()
v |= carry;
set_szc (v, 4, ma);
PD (v);
+ E1;
break;
case RXO_rorc:
@@ -1142,6 +1661,7 @@ decode_opcode ()
uma |= (carry ? 0x80000000UL : 0);
set_szc (uma, 4, mb);
PD (uma);
+ E1;
break;
case RXO_rotl:
@@ -1154,6 +1674,7 @@ decode_opcode ()
}
set_szc (uma, 4, mb);
PD (uma);
+ E1;
break;
case RXO_rotr:
@@ -1166,6 +1687,7 @@ decode_opcode ()
}
set_szc (uma, 4, mb);
PD (uma);
+ E1;
break;
case RXO_round:
@@ -1176,10 +1698,30 @@ decode_opcode ()
PD (mb);
tprintf("(int) %g = %d\n", int2float(ma), mb);
set_sz (mb, 4);
+ E (2);
break;
case RXO_rts:
- regs.r_pc = poppc ();
+ {
+#ifdef CYCLE_ACCURATE
+ int cyc = 5;
+#endif
+ regs.r_pc = poppc ();
+#ifdef CYCLE_ACCURATE
+ /* Note: specs say 5, chip says 3. */
+ if (regs.fast_return && regs.link_register == regs.r_pc)
+ {
+#ifdef CYCLE_STATS
+ fast_returns ++;
+#endif
+ tprintf("fast return bonus\n");
+ cyc -= 2;
+ }
+ cycles (cyc);
+ regs.fast_return = 0;
+ branch_alignment_penalty = 1;
+#endif
+ }
break;
case RXO_rtsd:
@@ -1190,12 +1732,39 @@ decode_opcode ()
put_reg (0, get_reg (0) + GS() - (opcode.op[0].reg-opcode.op[2].reg+1)*4);
if (opcode.op[2].reg == 0)
EXCEPTION (EX_UNDEFINED);
+#ifdef CYCLE_ACCURATE
+ tx = opcode.op[0].reg - opcode.op[2].reg + 1;
+#endif
for (i = opcode.op[2].reg; i <= opcode.op[0].reg; i ++)
- put_reg (i, pop ());
+ {
+ RLD (i);
+ put_reg (i, pop ());
+ }
+ }
+ else
+ {
+#ifdef CYCLE_ACCURATE
+ tx = 0;
+#endif
+ put_reg (0, get_reg (0) + GS());
+ }
+ put_reg (pc, poppc());
+#ifdef CYCLE_ACCURATE
+ if (regs.fast_return && regs.link_register == regs.r_pc)
+ {
+ tprintf("fast return bonus\n");
+#ifdef CYCLE_STATS
+ fast_returns ++;
+#endif
+ cycles (tx < 3 ? 3 : tx + 1);
}
else
- put_reg (0, get_reg (0) + GS());
- put_reg (pc, poppc ());
+ {
+ cycles (tx < 5 ? 5 : tx + 1);
+ }
+ regs.fast_return = 0;
+ branch_alignment_penalty = 1;
+#endif
break;
case RXO_sat:
@@ -1203,6 +1772,7 @@ decode_opcode ()
PD (0x7fffffffUL);
else if (FLAG_O && ! FLAG_S)
PD (0x80000000UL);
+ E1;
break;
case RXO_sbb:
@@ -1214,9 +1784,13 @@ decode_opcode ()
PD (1);
else
PD (0);
+ E1;
break;
case RXO_scmpu:
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
while (regs.r[3] != 0)
{
uma = mem_get_qi (regs.r[1] ++);
@@ -1229,6 +1803,7 @@ decode_opcode ()
set_zc (1, 1);
else
set_zc (0, ((int)uma - (int)umb) >= 0);
+ cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
break;
case RXO_setpsw:
@@ -1238,24 +1813,40 @@ decode_opcode ()
|| v == FLAGBIT_U))
break;
regs.r_psw |= v;
+ cycles (1);
break;
case RXO_smovb:
+ RL (3);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
while (regs.r[3])
{
uma = mem_get_qi (regs.r[2] --);
mem_put_qi (regs.r[1]--, uma);
regs.r[3] --;
}
+#ifdef CYCLE_ACCURATE
+ if (tx > 3)
+ cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
+ else
+ cycles (2 + 3 * (tx % 4));
+#endif
break;
case RXO_smovf:
+ RL (3);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
while (regs.r[3])
{
uma = mem_get_qi (regs.r[2] ++);
mem_put_qi (regs.r[1]++, uma);
regs.r[3] --;
}
+ cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
break;
case RXO_smovu:
@@ -1271,17 +1862,24 @@ decode_opcode ()
case RXO_shar: /* d = ma >> mb */
SHIFT_OP (sll, int, mb, >>=, 1);
+ E (1);
break;
case RXO_shll: /* d = ma << mb */
SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
+ E (1);
break;
case RXO_shlr: /* d = ma >> mb */
SHIFT_OP (ll, unsigned int, mb, >>=, 1);
+ E (1);
break;
case RXO_sstr:
+ RL (3);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
switch (opcode.size)
{
case RX_Long:
@@ -1291,6 +1889,7 @@ decode_opcode ()
regs.r[1] += 4;
regs.r[3] --;
}
+ cycles (2 + tx);
break;
case RX_Word:
while (regs.r[3] != 0)
@@ -1299,6 +1898,7 @@ decode_opcode ()
regs.r[1] += 2;
regs.r[3] --;
}
+ cycles (2 + (int)(tx / 2) + tx % 2);
break;
case RX_Byte:
while (regs.r[3] != 0)
@@ -1307,6 +1907,7 @@ decode_opcode ()
regs.r[1] ++;
regs.r[3] --;
}
+ cycles (2 + (int)(tx / 4) + tx % 4);
break;
default:
abort ();
@@ -1316,6 +1917,7 @@ decode_opcode ()
case RXO_stcc:
if (GS2())
PD (GS ());
+ E1;
break;
case RXO_stop:
@@ -1328,8 +1930,15 @@ decode_opcode ()
break;
case RXO_suntil:
+ RL(3);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
if (regs.r[3] == 0)
- break;
+ {
+ cycles (3);
+ break;
+ }
switch (opcode.size)
{
case RX_Long:
@@ -1342,6 +1951,7 @@ decode_opcode ()
if (umb == uma)
break;
}
+ cycles (3 + 3 * tx);
break;
case RX_Word:
uma = get_reg (2) & 0xffff;
@@ -1353,6 +1963,7 @@ decode_opcode ()
if (umb == uma)
break;
}
+ cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
break;
case RX_Byte:
uma = get_reg (2) & 0xff;
@@ -1364,6 +1975,7 @@ decode_opcode ()
if (umb == uma)
break;
}
+ cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
break;
default:
abort();
@@ -1375,6 +1987,10 @@ decode_opcode ()
break;
case RXO_swhile:
+ RL(3);
+#ifdef CYCLE_ACCURATE
+ tx = regs.r[3];
+#endif
if (regs.r[3] == 0)
break;
switch (opcode.size)
@@ -1389,6 +2005,7 @@ decode_opcode ()
if (umb != uma)
break;
}
+ cycles (3 + 3 * tx);
break;
case RX_Word:
uma = get_reg (2) & 0xffff;
@@ -1400,6 +2017,7 @@ decode_opcode ()
if (umb != uma)
break;
}
+ cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
break;
case RX_Byte:
uma = get_reg (2) & 0xff;
@@ -1411,6 +2029,7 @@ decode_opcode ()
if (umb != uma)
break;
}
+ cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
break;
default:
abort();
@@ -1427,9 +2046,18 @@ decode_opcode ()
return RX_MAKE_STOPPED(0);
case RXO_xchg:
+#ifdef CYCLE_ACCURATE
+ regs.m2m = 0;
+#endif
v = GS (); /* This is the memory operand, if any. */
PS (GD ()); /* and this may change the address register. */
PD (v);
+ E2;
+#ifdef CYCLE_ACCURATE
+ /* all M cycles happen during xchg's cycles. */
+ memory_dest = 0;
+ memory_source = 0;
+#endif
break;
case RXO_xor:
@@ -1440,5 +2068,122 @@ decode_opcode ()
EXCEPTION (EX_UNDEFINED);
}
+#ifdef CYCLE_ACCURATE
+ regs.m2m = 0;
+ if (memory_source)
+ regs.m2m |= M2M_SRC;
+ if (memory_dest)
+ regs.m2m |= M2M_DST;
+
+ regs.rt = new_rt;
+ new_rt = -1;
+#endif
+
+#ifdef CYCLE_STATS
+ if (prev_cycle_count == regs.cycle_count)
+ {
+ printf("Cycle count not updated! id %s\n", id_names[opcode.id]);
+ abort ();
+ }
+#endif
+
+#ifdef CYCLE_STATS
+ if (running_benchmark)
+ {
+ int omap = op_lookup (opcode.op[0].type, opcode.op[1].type, opcode.op[2].type);
+
+
+ cycles_per_id[opcode.id][omap] += regs.cycle_count - prev_cycle_count;
+ times_per_id[opcode.id][omap] ++;
+
+ times_per_pair[prev_opcode_id][po0][opcode.id][omap] ++;
+
+ prev_opcode_id = opcode.id;
+ po0 = omap;
+ }
+#endif
+
return RX_MAKE_STEPPED ();
}
+
+#ifdef CYCLE_STATS
+void
+reset_pipeline_stats (void)
+{
+ memset (cycles_per_id, 0, sizeof(cycles_per_id));
+ memset (times_per_id, 0, sizeof(times_per_id));
+ memory_stalls = 0;
+ register_stalls = 0;
+ branch_stalls = 0;
+ branch_alignment_stalls = 0;
+ fast_returns = 0;
+ memset (times_per_pair, 0, sizeof(times_per_pair));
+ running_benchmark = 1;
+
+ benchmark_start_cycle = regs.cycle_count;
+}
+
+void
+halt_pipeline_stats (void)
+{
+ running_benchmark = 0;
+ benchmark_end_cycle = regs.cycle_count;
+}
+#endif
+
+void
+pipeline_stats (void)
+{
+#ifdef CYCLE_STATS
+ int i, o1;
+ int p, p1;
+#endif
+
+#ifdef CYCLE_ACCURATE
+ if (verbose == 1)
+ {
+ printf ("cycles: %llu\n", regs.cycle_count);
+ return;
+ }
+
+ printf ("cycles: %13s\n", comma (regs.cycle_count));
+#endif
+
+#ifdef CYCLE_STATS
+ if (benchmark_start_cycle)
+ printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
+
+ printf("\n");
+ for (i = 0; i < N_RXO; i++)
+ for (o1 = 0; o1 < N_MAP; o1 ++)
+ if (times_per_id[i][o1])
+ printf("%13s %13s %7.2f %s %s\n",
+ comma (cycles_per_id[i][o1]),
+ comma (times_per_id[i][o1]),
+ (double)cycles_per_id[i][o1] / times_per_id[i][o1],
+ op_cache_string(o1),
+ id_names[i]+4);
+
+ printf("\n");
+ for (p = 0; p < N_RXO; p ++)
+ for (p1 = 0; p1 < N_MAP; p1 ++)
+ for (i = 0; i < N_RXO; i ++)
+ for (o1 = 0; o1 < N_MAP; o1 ++)
+ if (times_per_pair[p][p1][i][o1])
+ {
+ printf("%13s %s %-9s -> %s %s\n",
+ comma (times_per_pair[p][p1][i][o1]),
+ op_cache_string(p1),
+ id_names[p]+4,
+ op_cache_string(o1),
+ id_names[i]+4);
+ }
+
+ printf("\n");
+ printf("%13s memory stalls\n", comma (memory_stalls));
+ printf("%13s register stalls\n", comma (register_stalls));
+ printf("%13s branches taken (non-return)\n", comma (branch_stalls));
+ printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
+ printf("%13s fast returns\n", comma (fast_returns));
+#endif
+}
diff --git a/sim/rx/trace.c b/sim/rx/trace.c
index cab05ff..add37ea 100644
--- a/sim/rx/trace.c
+++ b/sim/rx/trace.c
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@@ -321,7 +322,13 @@ sim_disasm_one (void)
}
opbuf[0] = 0;
- printf ("\033[33m%06x: ", mypc);
+#ifdef CYCLE_ACCURATE
+ printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc);
+#else
+ printf ("\033[33m %06x: ", mypc);
+
+#endif
+
max = print_insn_rx (mypc, & info);
for (i = 0; i < max; i++)