summaryrefslogtreecommitdiff
path: root/nacl/cpucycles/cortex.c
diff options
context:
space:
mode:
Diffstat (limited to 'nacl/cpucycles/cortex.c')
-rw-r--r--nacl/cpucycles/cortex.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/nacl/cpucycles/cortex.c b/nacl/cpucycles/cortex.c
new file mode 100644
index 00000000..07e2fa02
--- /dev/null
+++ b/nacl/cpucycles/cortex.c
@@ -0,0 +1,73 @@
1/*
2cpucycles/cortex.c version 20101203
3D. J. Bernstein
4Public domain.
5*/
6
7#define SCALE 1
8#include <time.h>
9#include <unistd.h>
10#include <sys/time.h>
11
12static int enabled = 0;
13
14static int prev[3];
15static unsigned long long prevcycles = 0;
16static int now[3];
17static long long cyclespersec = 0;
18
19static void readticks(unsigned int *result)
20{
21 struct timeval t;
22 unsigned int cc;
23 if (!enabled) {
24 asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(17));
25 asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f));
26 asm volatile("mcr p15, 0, %0, c9, c12, 3" :: "r"(0x8000000f));
27 enabled = 1;
28 }
29 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(cc));
30 gettimeofday(&t,(struct timezone *) 0);
31 result[0] = cc;
32 result[1] = t.tv_usec;
33 result[2] = t.tv_sec;
34}
35
36long long cpucycles_cortex(void)
37{
38 unsigned long long delta4;
39 int deltan;
40 int deltas;
41 unsigned long long guesscycles;
42
43 readticks(now);
44 delta4 = (unsigned int) (now[0] - prev[0]); /* unsigned change in number of cycles mod 2^32 */
45 deltan = now[1] - prev[1]; /* signed change in number of nanoseconds mod 10^9 */
46 deltas = now[2] - prev[2]; /* signed change in number of seconds */
47 if ((deltas == 0 && deltan < 200000) || (deltas == 1 && deltan < -800000))
48 return (prevcycles + delta4) * SCALE;
49
50 prev[0] = now[0];
51 prev[1] = now[1];
52 prev[2] = now[2];
53
54 if ((deltas == 0 && deltan < 300000) || (deltas == 1 && deltan < -700000)) {
55 // actual number of cycles cannot have increased by 2^32 in <0.3ms
56 cyclespersec = 1000000 * (unsigned long long) delta4;
57 cyclespersec /= deltan + 1000000 * (long long) deltas;
58 } else {
59 guesscycles = deltas * cyclespersec;
60 guesscycles += (deltan * cyclespersec) / 1000000;
61 while (delta4 + 2147483648ULL < guesscycles) delta4 += 4294967296ULL;
62 /* XXX: could do longer-term extrapolation here */
63 }
64
65 prevcycles += delta4;
66 return prevcycles * SCALE;
67}
68
69long long cpucycles_cortex_persecond(void)
70{
71 while (!cyclespersec) cpucycles_cortex();
72 return cyclespersec * SCALE;
73}