summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2020-08-20 18:06:29 -0700
committer Aaron Giles <aaron@aarongiles.com>2020-08-20 18:06:29 -0700
commite9a0dc19d87ea7a7ffc3ab59f4810d23b1a672ef (patch)
tree369ac21df8cb6cad4dbc59c2425371596c87da7e
parent28cf65c905a8f5fa8d1ed153e44374fb40ef9040 (diff)
pit8253: Fix cycles computation error due to using floating-point.
-rw-r--r--src/devices/machine/pit8253.cpp39
1 files changed, 38 insertions, 1 deletions
diff --git a/src/devices/machine/pit8253.cpp b/src/devices/machine/pit8253.cpp
index 2e73aecbcb9..f0f4450e90d 100644
--- a/src/devices/machine/pit8253.cpp
+++ b/src/devices/machine/pit8253.cpp
@@ -714,7 +714,44 @@ void pit_counter_device::update()
if (now > m_last_updated)
{
attotime elapsed_time = now - m_last_updated;
- elapsed_cycles = elapsed_time.as_double() * m_clockin;
+
+ // in the case of sub-Hz frequencies, just loop; there's not going to be many
+ if (m_clock_period.m_seconds != 0)
+ {
+ while (elapsed_time >= m_clock_period)
+ {
+ elapsed_cycles++;
+ elapsed_time -= m_clock_period;
+ }
+ }
+
+ // otherwise, compute it a straightforward way
+ else
+ {
+ elapsed_cycles = elapsed_time.m_attoseconds / m_clock_period.m_attoseconds;
+
+ // not expecting to see many cases of this, but just in case, let's do it right
+ if (elapsed_time.m_seconds != 0)
+ {
+ // first account for the elapsed_cycles counted above (guaranteed to be <= elapsed_time.m_attoseconds)
+ elapsed_time.m_attoseconds -= elapsed_cycles * m_clock_period.m_attoseconds;
+
+ // now compute the integral cycles per second based on the clock period
+ int64_t cycles_per_second = ATTOSECONDS_PER_SECOND / m_clock_period.m_attoseconds;
+
+ // add that many times the number of elapsed seconds
+ elapsed_cycles += cycles_per_second * elapsed_time.m_seconds;
+
+ // now compute how many attoseconds we missed for each full second (will be 0 for integral values)
+ int64_t remainder_per_second = ATTOSECONDS_PER_SECOND - cycles_per_second * m_clock_period.m_attoseconds;
+
+ // add those to the elapsed attoseconds
+ elapsed_time.m_attoseconds += elapsed_time.m_seconds * remainder_per_second;
+
+ // finally, see if that adds up to any additional cycles
+ elapsed_cycles += elapsed_time.m_attoseconds / m_clock_period.m_attoseconds;
+ }
+ }
LOG2("update(): %d elapsed_cycles\n", elapsed_cycles);