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