native_clock.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #ifdef ANDROID
  4. #include <sys/system_properties.h>
  5. #endif
  6. #include "common/arm64/native_clock.h"
  7. namespace Common::Arm64 {
  8. namespace {
  9. NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) {
  10. return (static_cast<NativeClock::FactorType>(num) << 64) / den;
  11. }
  12. u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) {
  13. return static_cast<u64>((m * factor) >> 64);
  14. }
  15. } // namespace
  16. NativeClock::NativeClock() {
  17. const u64 host_cntfrq = GetHostCNTFRQ();
  18. ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
  19. us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
  20. ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
  21. guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
  22. gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
  23. }
  24. std::chrono::nanoseconds NativeClock::GetTimeNS() const {
  25. return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
  26. }
  27. std::chrono::microseconds NativeClock::GetTimeUS() const {
  28. return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
  29. }
  30. std::chrono::milliseconds NativeClock::GetTimeMS() const {
  31. return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
  32. }
  33. s64 NativeClock::GetCNTPCT() const {
  34. return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
  35. }
  36. s64 NativeClock::GetGPUTick() const {
  37. return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
  38. }
  39. s64 NativeClock::GetUptime() const {
  40. s64 cntvct_el0 = 0;
  41. asm volatile("dsb ish\n\t"
  42. "mrs %[cntvct_el0], cntvct_el0\n\t"
  43. "dsb ish\n\t"
  44. : [cntvct_el0] "=r"(cntvct_el0));
  45. return cntvct_el0;
  46. }
  47. bool NativeClock::IsNative() const {
  48. return true;
  49. }
  50. s64 NativeClock::GetHostCNTFRQ() {
  51. u64 cntfrq_el0 = 0;
  52. std::string_view board{""};
  53. #ifdef ANDROID
  54. char buffer[PROP_VALUE_MAX];
  55. int len{__system_property_get("ro.product.board", buffer)};
  56. board = std::string_view(buffer, static_cast<size_t>(len));
  57. #endif
  58. if (board == "s5e9925") { // Exynos 2200
  59. cntfrq_el0 = 25600000;
  60. } else if (board == "exynos2100") { // Exynos 2100
  61. cntfrq_el0 = 26000000;
  62. } else if (board == "exynos9810") { // Exynos 9810
  63. cntfrq_el0 = 26000000;
  64. } else if (board == "s5e8825") { // Exynos 1280
  65. cntfrq_el0 = 26000000;
  66. } else {
  67. asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
  68. }
  69. return cntfrq_el0;
  70. }
  71. } // namespace Common::Arm64