|
21 | 21 | #endif |
22 | 22 |
|
23 | 23 | #if defined(__powerpc__) || defined(__ppc__) |
| 24 | +#ifdef __GLIBC__ |
24 | 25 | #include <sys/platform/ppc.h> |
| 26 | +#elif defined(__FreeBSD__) |
| 27 | +#include <sys/sysctl.h> |
| 28 | +#include <sys/types.h> |
| 29 | +#endif |
25 | 30 | #endif |
26 | 31 |
|
27 | 32 | #include "absl/base/internal/sysinfo.h" |
@@ -57,11 +62,43 @@ double UnscaledCycleClock::Frequency() { |
57 | 62 | #elif defined(__powerpc__) || defined(__ppc__) |
58 | 63 |
|
59 | 64 | int64_t UnscaledCycleClock::Now() { |
| 65 | +#ifdef __GLIBC__ |
60 | 66 | return __ppc_get_timebase(); |
| 67 | +#else |
| 68 | +#ifdef __powerpc64__ |
| 69 | + int64_t tbr; |
| 70 | + asm volatile("mfspr %0, 268" : "=r"(tbr)); |
| 71 | + return tbr; |
| 72 | +#else |
| 73 | + int32_t tbu, tbl, tmp; |
| 74 | + asm volatile( |
| 75 | + "0:\n" |
| 76 | + "mftbu %[hi32]\n" |
| 77 | + "mftb %[lo32]\n" |
| 78 | + "mftbu %[tmp]\n" |
| 79 | + "cmpw %[tmp],%[hi32]\n" |
| 80 | + "bne 0b\n" |
| 81 | + : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp)); |
| 82 | + return (static_cast<int64_t>(tbu) << 32) | tbl; |
| 83 | +#endif |
| 84 | +#endif |
61 | 85 | } |
62 | 86 |
|
63 | 87 | double UnscaledCycleClock::Frequency() { |
| 88 | +#ifdef __GLIBC__ |
64 | 89 | return __ppc_get_timebase_freq(); |
| 90 | +#elif defined(__FreeBSD__) |
| 91 | + static once_flag init_timebase_frequency_once; |
| 92 | + static double timebase_frequency = 0.0; |
| 93 | + base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() { |
| 94 | + size_t length = sizeof(timebase_frequency); |
| 95 | + sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency, |
| 96 | + &length, nullptr, 0); |
| 97 | + }); |
| 98 | + return timebase_frequency; |
| 99 | +#else |
| 100 | +#error Must implement UnscaledCycleClock::Frequency() |
| 101 | +#endif |
65 | 102 | } |
66 | 103 |
|
67 | 104 | #elif defined(__aarch64__) |
|
0 commit comments