CoreTiming: Fix ARM11 clock rate, add ability to use nanoseconds in core timing, add overflow handling

This commit is contained in:
B3n30 2017-11-13 12:11:43 +01:00
parent b6dd8ef874
commit e4d51b8ff4
4 changed files with 66 additions and 15 deletions

View File

@ -5,7 +5,7 @@ cache:
- C:\ProgramData\chocolatey\bin -> appveyor.yml
- C:\ProgramData\chocolatey\lib -> appveyor.yml
os: Previous Visual Studio 2017
os: Visual Studio 2017
environment:
# Tell msys2 to add mingw64 to the path

View File

@ -5,8 +5,10 @@
#pragma once
#include <functional>
#include <limits>
#include <string>
#include "common/common_types.h"
#include "common/logging/log.h"
// This is a system to schedule events into the emulated machine's future. Time is measured
// in main CPU clock cycles.
@ -21,35 +23,87 @@
// inside callback:
// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever")
constexpr int BASE_CLOCK_RATE_ARM11 = 268123480;
// The actual timing is 268,111,855.956 Hz
constexpr s64 BASE_CLOCK_RATE_ARM11 = 268111856;
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / 268111856;
extern int g_clock_rate_arm11;
inline s64 msToCycles(int ms) {
return (s64)g_clock_rate_arm11 / 1000 * ms;
// since mx is int there is no way to overflow
return g_clock_rate_arm11 * static_cast<s64>(ms) / 1000;
}
inline s64 msToCycles(float ms) {
return (s64)(g_clock_rate_arm11 * ms * (0.001f));
return static_cast<s64>(g_clock_rate_arm11 * ms * (0.001f));
}
inline s64 msToCycles(double ms) {
return (s64)(g_clock_rate_arm11 * ms * (0.001));
return static_cast<s64>(g_clock_rate_arm11 * ms * (0.001));
}
inline s64 usToCycles(float us) {
return (s64)(g_clock_rate_arm11 * us * (0.000001f));
return static_cast<s64>(g_clock_rate_arm11 * us * (0.000001f));
}
inline s64 usToCycles(int us) {
return (g_clock_rate_arm11 / 1000000 * (s64)us);
return (g_clock_rate_arm11 * static_cast<s64>(us) / 1000000);
}
inline s64 usToCycles(s64 us) {
return (g_clock_rate_arm11 / 1000000 * us);
if ((us / 1000000) > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
} else if (us > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * (us / 1000000));
}
return (g_clock_rate_arm11 * us / 1000000);
}
inline s64 usToCycles(u64 us) {
return (s64)(g_clock_rate_arm11 / 1000000 * us);
if ((us / 1000000) > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
} else if (us > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * static_cast<s64>(us / 1000000));
}
return (g_clock_rate_arm11 * static_cast<s64>(us) / 1000000);
}
inline s64 nsToCycles(float ns) {
return static_cast<s64>(g_clock_rate_arm11 * ns * (0.000000001f));
}
inline s64 nsToCycles(int ns) {
return (g_clock_rate_arm11 * static_cast<s64>(ns) / 1000000000);
}
inline s64 nsToCycles(s64 ns) {
if ((ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
} else if (ns > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * (ns / 1000000000));
}
return (g_clock_rate_arm11 * ns / 1000000000);
}
inline s64 nsToCycles(u64 ns) {
if ((ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max();
} else if (ns > MAX_VALUE_TO_MULTIPLY) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * static_cast<s64>(ns / 1000000000));
}
return (g_clock_rate_arm11 * static_cast<s64>(ns) / 1000000000);
}
inline u64 cyclesToNs(s64 cycles) {
return cycles / (g_clock_rate_arm11 / 1000000000);
}
inline s64 cyclesToUs(s64 cycles) {

View File

@ -266,8 +266,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
if (nanoseconds == -1)
return;
u64 microseconds = nanoseconds / 1000;
CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle);
}
void Thread::ResumeFromWait() {

View File

@ -57,8 +57,7 @@ void Timer::Set(s64 initial, s64 interval) {
// Immediately invoke the callback
Signal(0);
} else {
u64 initial_microseconds = initial / 1000;
CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type,
callback_handle);
}
}
@ -88,8 +87,7 @@ void Timer::Signal(int cycles_late) {
if (interval_delay != 0) {
// Reschedule the timer with the interval delay
u64 interval_microseconds = interval_delay / 1000;
CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late,
timer_callback_event_type, callback_handle);
}
}