aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-10-25 13:44:14 -0700
committerH. Peter Anvin <hpa@zytor.com>2018-10-25 14:17:02 -0700
commitbbc7348b06d5ec333537b7b75da5be12906c6978 (patch)
tree0629b80439442d445c5f1aa621ce8bba1e16a3b3
parenta6dd94aa2ec4a88a4052fda0c208bd3d936fcc41 (diff)
downloadabc80sim-bbc7348b06d5ec333537b7b75da5be12906c6978.tar.gz
abc80sim-bbc7348b06d5ec333537b7b75da5be12906c6978.tar.xz
abc80sim-bbc7348b06d5ec333537b7b75da5be12906c6978.zip
clock: only check wall time every 64 T-states
nstime() can be pretty expensive, so only check the timing every 64 T-states; this corresponds to 21 ┬Ás at 3 MHz. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--autoconf/m4/pa_arg_bool.m410
-rw-r--r--autoconf/m4/pa_arg_disabled.m44
-rw-r--r--autoconf/m4/pa_arg_enabled.m42
-rw-r--r--clock.c52
-rw-r--r--configure.ac4
5 files changed, 50 insertions, 22 deletions
diff --git a/autoconf/m4/pa_arg_bool.m4 b/autoconf/m4/pa_arg_bool.m4
index 92f5765..5289ed4 100644
--- a/autoconf/m4/pa_arg_bool.m4
+++ b/autoconf/m4/pa_arg_bool.m4
@@ -8,12 +8,12 @@ dnl test for $enableval and the AS_HELP_STRING definition. This is only
dnl to be used for boolean options.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ARG_BOOL],
-[m4_pushdef([pa_enableval],m4_default(m4_normalize([$3]),[yes]))
- m4_pushdef([pa_option],m4_case([pa_enableval],[no],[disable],[enable]))
+[m4_pushdef([pa_default],m4_default(m4_normalize([$3]),[no]))
+ m4_pushdef([pa_option],m4_case(pa_default,[yes],[disable],[enable]))
AC_ARG_ENABLE([$1],
[AS_HELP_STRING([--]m4_defn([pa_option])[-$1],[$2])],
- [[pa_arg_bool_enableval="]m4_defn([pa_enableval])["]],
- [pa_arg_bool_enableval=no])
- m4_popdef([pa_enableval],[pa_option])
+ [pa_arg_bool_enableval="$enableval"],
+ [pa_arg_bool_enableval="]m4_defn([pa_default])["])
+ m4_popdef([pa_option], [pa_default])
AS_IF([test x"$pa_arg_bool_enableval" != xno], [$4], [$5])
])
diff --git a/autoconf/m4/pa_arg_disabled.m4 b/autoconf/m4/pa_arg_disabled.m4
new file mode 100644
index 0000000..42f4ce8
--- /dev/null
+++ b/autoconf/m4/pa_arg_disabled.m4
@@ -0,0 +1,4 @@
+dnl --------------------------------------------------------------------------
+dnl PA_ARG_DISABLED(option,helptext,disabled_action,enabled_action)
+dnl --------------------------------------------------------------------------
+AC_DEFUN([PA_ARG_DISABLED],[PA_ARG_BOOL([$1],[$2],yes,[$4],[$3])])
diff --git a/autoconf/m4/pa_arg_enabled.m4 b/autoconf/m4/pa_arg_enabled.m4
index f08c9e0..7d66a21 100644
--- a/autoconf/m4/pa_arg_enabled.m4
+++ b/autoconf/m4/pa_arg_enabled.m4
@@ -1,4 +1,4 @@
dnl --------------------------------------------------------------------------
dnl PA_ARG_ENABLED(option,helptext,enabled_action,disabled_action)
dnl --------------------------------------------------------------------------
-AC_DEFUN([PA_ARG_ENABLED],[PA_ARG_BOOL([$1],[$2],yes,[$3],[$4])])
+AC_DEFUN([PA_ARG_ENABLED],[PA_ARG_BOOL([$1],[$2],no,[$3],[$4])])
diff --git a/clock.c b/clock.c
index 70e9dab..3e358ff 100644
--- a/clock.c
+++ b/clock.c
@@ -104,30 +104,50 @@ static void consider_napping(uint64_t now, uint64_t next)
ref_tstate = TSTATE;
}
+/*
+ * Even on systems where it is highly optimized, nstime() can take
+ * quite a while to run. Therefore, only check wall time after
+ * a certain number of simulated T-states.
+ */
+#define CHECK_FREQUENCY 64
+
/* Poll for timers - these the only external event we look for */
void z80_poll_external(void)
{
- uint64_t now = nstime();
- uint64_t next = ~UINT64_C(0);
+ uint64_t now;
+ static uint64_t next = 0;
int i;
bool sleepy = limit_speed;
+ static uint64_t next_check_tstate;
+
+ if (likely(TSTATE < next_check_tstate))
+ return;
+
+ next_check_tstate += CHECK_FREQUENCY;
+
+ now = nstime();
+
+ if (unlikely(now >= next)) {
+ next = UINT64_MAX;
- for (i = 0; i < ntimers; i++) {
- struct abctimer *t = &timers[i];
- if (t->period) {
- uint64_t tnext = t->last + t->period;
- if (unlikely(now >= tnext)) {
- t->last += t->period;
+ for (i = 0; i < ntimers; i++) {
+ struct abctimer *t = &timers[i];
+ if (t->period) {
+ uint64_t tnext = t->last + t->period;
if (unlikely(now >= tnext)) {
- /* Missed tick(s), advance to skip missed */
- t->last = now - (now - t->last) % t->period;
+ t->last += t->period;
+ if (unlikely(now >= tnext)) {
+ /* Missed tick(s), advance to skip missed */
+ t->last = now - (now - t->last) % t->period;
+ tnext = t->last + t->period;
+ }
+ /* TSTATE value corresponding to t->last */
+ t->ltst = TSTATE - (now - t->last)*tstate_per_ns;
+ t->func();
+ sleepy = false; /* Just in case "now" is too far behind now */
}
- /* TSTATE value corresponding to t->last */
- t->ltst = TSTATE - (now - t->last)*tstate_per_ns;
- t->func();
- sleepy = false; /* Just in case "now" is too far behind now */
- } else if (next > tnext) {
- next = tnext; /* The next event is closer than you thought */
+ if (next > tnext)
+ next = tnext; /* The next event is closer than you thought */
}
}
}
diff --git a/configure.ac b/configure.ac
index 7606662..d3a0f58 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,10 @@ dnl Some environments abuse __STRICT_ANSI__ to disable some
dnl function declarations
PA_ADD_CPPFLAGS([-U__STRICT_ANSI__])
+dnl Add -O3 unless disabled; seems to help this program quite a bit
+PA_ARG_DISABLED([O3], [don't compile with -O3 optimization],
+ [], [PA_ADD_CFLAGS(-O3)])
+
dnl Don't put things in common if we can avoid it. We don't want to
dnl assume all compilers support common, and this will help find those
dnl problems. This also works around an OSX linker problem.