mips.c 1.8 KB

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