diff options
Diffstat (limited to 'nacl/cpucycles/powerpccpuinfo.c')
-rw-r--r-- | nacl/cpucycles/powerpccpuinfo.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/nacl/cpucycles/powerpccpuinfo.c b/nacl/cpucycles/powerpccpuinfo.c new file mode 100644 index 00000000..b70c745a --- /dev/null +++ b/nacl/cpucycles/powerpccpuinfo.c | |||
@@ -0,0 +1,95 @@ | |||
1 | #include <time.h> | ||
2 | #include <stdio.h> | ||
3 | #include <unistd.h> | ||
4 | #include <sys/time.h> | ||
5 | #include <sys/types.h> | ||
6 | #include "osfreq.c" | ||
7 | |||
8 | static long myround(double u) | ||
9 | { | ||
10 | long result = u; | ||
11 | while (result + 0.5 < u) result += 1; | ||
12 | while (result - 0.5 > u) result -= 1; | ||
13 | return result; | ||
14 | } | ||
15 | |||
16 | static long long microseconds(void) | ||
17 | { | ||
18 | struct timeval t; | ||
19 | gettimeofday(&t,(struct timezone *) 0); | ||
20 | return t.tv_sec * (long long) 1000000 + t.tv_usec; | ||
21 | } | ||
22 | |||
23 | static int tbshift = 0; | ||
24 | |||
25 | static long long timebase(void) | ||
26 | { | ||
27 | unsigned long high; | ||
28 | unsigned long low; | ||
29 | unsigned long newhigh; | ||
30 | unsigned long long result; | ||
31 | asm volatile( | ||
32 | "7:mftbu %0;mftb %1;mftbu %2;cmpw %0,%2;bne 7b" | ||
33 | : "=r" (high), "=r" (low), "=r" (newhigh) | ||
34 | ); | ||
35 | result = high; | ||
36 | result <<= 32; | ||
37 | result |= low; | ||
38 | return result >> tbshift; | ||
39 | } | ||
40 | |||
41 | static double cpufrequency = 0; | ||
42 | static long tbcycles = 0; | ||
43 | |||
44 | static double guesstbcycles(void) | ||
45 | { | ||
46 | long long tb0; long long us0; | ||
47 | long long tb1; long long us1; | ||
48 | |||
49 | tb0 = timebase(); | ||
50 | us0 = microseconds(); | ||
51 | do { | ||
52 | tb1 = timebase(); | ||
53 | us1 = microseconds(); | ||
54 | } while (us1 - us0 < 10000 || tb1 - tb0 < 1000); | ||
55 | if (tb1 <= tb0) return 0; | ||
56 | tb1 -= tb0; | ||
57 | us1 -= us0; | ||
58 | return (cpufrequency * 0.000001 * (double) us1) / (double) tb1; | ||
59 | } | ||
60 | |||
61 | static void init(void) | ||
62 | { | ||
63 | int loop; | ||
64 | double guess1; | ||
65 | double guess2; | ||
66 | |||
67 | cpufrequency = osfreq(); | ||
68 | if (!cpufrequency) return; | ||
69 | |||
70 | for (tbshift = 0;tbshift < 10;++tbshift) { | ||
71 | for (loop = 0;loop < 100;++loop) { | ||
72 | guess1 = guesstbcycles(); | ||
73 | guess2 = guesstbcycles(); | ||
74 | tbcycles = myround(guess1); | ||
75 | if (guess1 - tbcycles > 0.1) continue; | ||
76 | if (tbcycles - guess1 > 0.1) continue; | ||
77 | if (guess2 - tbcycles > 0.1) continue; | ||
78 | if (tbcycles - guess2 > 0.1) continue; | ||
79 | return; | ||
80 | } | ||
81 | } | ||
82 | tbcycles = 0; | ||
83 | } | ||
84 | |||
85 | long long cpucycles_powerpccpuinfo(void) | ||
86 | { | ||
87 | if (!tbcycles) init(); | ||
88 | return timebase() * tbcycles; | ||
89 | } | ||
90 | |||
91 | long long cpucycles_powerpccpuinfo_persecond(void) | ||
92 | { | ||
93 | if (!tbcycles) init(); | ||
94 | return cpufrequency; | ||
95 | } | ||