/*----------------------------------------------------------------------------*/

/*
 * Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
 * Author:  Don Heller, dheller@scl.ameslab.gov
 * Last revised:  5 October 2001
 */

#if defined(PMC_P5) || defined(PMC_P6) || defined(PMC_K7)
#endif  /* PMC_P5 PMC_P6 PMC_K7 */
 
#if defined(PMC_P15)
/* begin unfinished */
/* end unfinished */
#endif  /* PMC_P15 */

/*----------------------------------------------------------------------------*/

/* compile with
 *   gcc `pmc_options` -o pmc_query -UPMC_TEST pmc_test.c
 *   gcc `pmc_options` -o pmc_test  -DPMC_TEST pmc_test.c
 */

/*----------------------------------------------------------------------------*/

#include <stdio.h>

/* for open() */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/* for read(), write(), lseek() */
#include <sys/types.h>
#include <unistd.h>

/* for errno, strerror() */
#include <errno.h>
#include <string.h>

/* for LINUX_VERSION_CODE */
#include <linux/version.h>

/* for uname() */
#include <sys/utsname.h>

/* for exit() */
#include <stdlib.h>

/*----------------------------------------------------------------------------*/

#include <pmc_dev.h>
#include <pmc_lib.h>
#include <pmc_sys.h>

/*----------------------------------------------------------------------------*/

pmc_uint32_t reg32;
pmc_uint64_t reg64, val;
pmc_uint64_t reg[1 + pmc_event_counters];

#define fmt8 "0x%08lx"
#define fmt16 "0x%016llx"

/*----------------------------------------------------------------------------*/

#if defined(PMC_P15)
	/* 18 counter, 18 cccr, 45 escr registers */
pmc_uint64_t p15_reg[1+18+18+46];
void print_p15_counters(pmc_uint64_t reg[18]);
void print_p15_cccrs(pmc_uint64_t reg[18]);
void print_p15_escrs(pmc_uint64_t reg[46]);
#endif	/* PMC_P15 */

/*----------------------------------------------------------------------------*/

int main(int argc, char *argv[])
{
  int DevPMC = -1;	/* file descriptor */
  int ret;

#ifdef PMC_TEST
  int i;

#ifdef PMC_ALLOW_SYSTEM_TEST
  int j;

  char * test_name[] = {
    "overhead",
    "cpuid",
    "rdtsc",
    "rdpmc 0",
    "rdpmc 1",
#ifdef PMC_2
    "rdpmc 2",
#endif
#ifdef PMC_3
    "rdpmc 3",
#endif
    "rdpmc all",
    "rdmsr tsc",
    "rdmsr 0",
    "rdmsr 1",
#ifdef PMC_2
    "rdmsr 2",
#endif
#ifdef PMC_3
    "rdmsr 3",
#endif
    "rdmsr all",
    "rdmsr control 0",
#ifdef PMC_CONTROL_1
    "rdmsr control 1",
#endif
#ifdef PMC_CONTROL_2
    "rdmsr control 2",
#endif
#ifdef PMC_CONTROL_3
    "rdmsr control 3",
#endif
    "rdmsr control all",
    "rd,wrmsr control 0",
#ifdef PMC_CONTROL_1
    "rd,wrmsr control 1",
#endif
#ifdef PMC_CONTROL_2
    "rd,wrmsr control 2",
#endif
#ifdef PMC_CONTROL_3
    "rd,wrmsr control 3",
#endif
    "rd,wrmsr control all",
    "store and reload"
  };

  int test_code[] = {
    PMC_TEST_OVERHEAD,
    PMC_TEST_CPUID,
    PMC_TEST_RDTSC,
    PMC_TEST_RDPMC_0,
    PMC_TEST_RDPMC_1,
#ifdef PMC_2
    PMC_TEST_RDPMC_2,
#endif
#ifdef PMC_3
    PMC_TEST_RDPMC_3,
#endif
    PMC_TEST_RDPMC_ALL,
    PMC_TEST_RDMSR_TSC,
    PMC_TEST_RDMSR_0,
    PMC_TEST_RDMSR_1,
#ifdef PMC_2
    PMC_TEST_RDMSR_2,
#endif
#ifdef PMC_3
    PMC_TEST_RDMSR_3,
#endif
    PMC_TEST_RDMSR_ALL,
    PMC_TEST_RDMSR_CONTROL_0,
#ifdef PMC_CONTROL_1
    PMC_TEST_RDMSR_CONTROL_1,
#endif
#ifdef PMC_CONTROL_2
    PMC_TEST_RDMSR_CONTROL_2,
#endif
#ifdef PMC_CONTROL_3
    PMC_TEST_RDMSR_CONTROL_3,
#endif
    PMC_TEST_RDMSR_CONTROL_ALL,
    PMC_TEST_RDWRMSR_CONTROL_0,
#ifdef PMC_CONTROL_1
    PMC_TEST_RDWRMSR_CONTROL_1,
#endif
#ifdef PMC_CONTROL_2
    PMC_TEST_RDWRMSR_CONTROL_2,
#endif
#ifdef PMC_CONTROL_3
    PMC_TEST_RDWRMSR_CONTROL_3,
#endif
    PMC_TEST_RDWRMSR_CONTROL_ALL,
    PMC_TEST_STORE_AND_RELOAD
  };
#endif	/* PMC_ALLOW_SYSTEM_TEST */

#endif	/* PMC_TEST */

  printf("Linux:\n");

  printf("  from /usr/include/linux/version.h\n");
  printf("    UTS_RELEASE = %s\n", UTS_RELEASE);
  printf("    LINUX_VERSION_CODE = 0x%x\n", LINUX_VERSION_CODE);

  {
    struct utsname buf;
    if (uname(&buf) == -1)
      { printf("  no info from uname(): %s\n", strerror(errno)); }
    else
      {
	printf("  from uname()\n");
        printf("    release = %s\n", buf.release);
        printf("    version = %s\n", buf.version);
      }
  }

  DevPMC = open("/dev/pmc", O_RDWR);

  if (DevPMC == -1)
    {
      printf("%s: /dev/pmc failed to open: %s\n", argv[0], strerror(errno));
      exit(1);
    }

  printf("/dev/pmc:\n");

  ret = (int) lseek(DevPMC, PMC_DEVICE_SOFTWARE_VERSION, SEEK_SET);
  printf("  version %d.%02d, ", ret/100, ret%100);

  ret = (int) lseek(DevPMC, PMC_DEVICE_HARDWARE_TYPE, SEEK_SET);
  printf("compiled for %s, ", pmc_cpu[ret]);

  ret = (int) lseek(DevPMC, PMC_DEVICE_SOFTWARE_VERSION_KERNEL, SEEK_SET);
  printf("Linux kernel %d.%d.%d",
	(ret >> 16) & 0xff, (ret >> 8) & 0xff, ret & 0xff);

  ret = (int) lseek(DevPMC, PMC_DEVICE_SOFTWARE_VERSION_SMP, SEEK_SET);
  if (ret)
    { printf(" (SMP)"); }

  printf("\n");

  printf("processor:\n");

  /* L1 and L2 cache */
  ret = (int) lseek(DevPMC, PMC_QUERY_CACHE, SEEK_SET);
  if (ret == 1)
    { printf("  cache is enabled\n"); }
  else if (ret == 0)
    { printf("  cache is disabled (this is not good)\n"); }
  else
    { printf("  cache status is not available\n"); }

  /* Time Stamp Disable bit (CR4.TSD, bit 2) */
  ret = (int) lseek(DevPMC, PMC_QUERY_RDTSC, SEEK_SET);
  if (ret == 1)
    { printf("  rdtsc is disabled (this is not good)\n"); }
  else if (ret == 0)
    { printf("  rdtsc is enabled\n"); }
  else
    { printf("  rdtsc status is not available\n"); }

  /* Performance Counter Enable bit (CR4.PCE, bit 8) */
  ret = (int) lseek(DevPMC, PMC_QUERY_RDPMC, SEEK_SET);
  if (ret == 1)
    { printf("  rdpmc is enabled\n"); }
  else if (ret == 0)
    { printf("  rdpmc is disabled (try running pmc_enable)\n"); }
  else
    { printf("  rdpmc is not available\n"); }	/* original Pentium */

  /* Alignment Mask bit (CR0.AM, bit 18) */
  ret = (int) lseek(DevPMC, PMC_QUERY_ALIGNMENT_CHECKING, SEEK_SET);
  if (ret == 1)
    { printf("  system alignment checking is enabled\n"); }
  else if (ret == 0)
    { printf("  system alignment checking is disabled\n"); }
  else
    { printf("  system alignment checking, status is not available\n"); }


#if defined(PMC_P6) || defined (PMC_P15)
  /* local APIC */
  ret = read(DevPMC, &reg64, PMC_READ_APICBASE);
  if (ret == 8)
    {
      printf("local APIC:\n");
      if (reg64.bits32.low & 0x100)
	{ printf("  this is the bootstrap processor\n"); }
      else
	{ printf("  this is not the bootstrap processor\n"); }
      if (reg64.bits32.low & 0x800)
	{ printf("  the local APIC is enabled"); }
      else
	{ printf("  the local APIC is disabled"); }
      printf(", base address = 0x%lx:%08lx\n",
	reg64.bits32.high & 0x0000000f,	/* 36-bit address */
	reg64.bits32.low  & 0xfffff000);
    }
  else
    {
      printf("local APIC, status is not available\n");
      /* future - check the CPUID response */
    }
#endif	/* PMC_P6 PMC_P15 */

#if defined(PMC_P15)
  /* Frequency Configuration */
  ret = read(DevPMC, &reg64, PMC_READ_BUS_FREQUENCY);
  if (ret == 8)
    {
      int sbs[8] = { 100, 0, 0, 0, 0, 0, 0, 0 };
      printf("Frequency Configuration:\n");
      printf("  scalable bus speed = %d MHz\n",
	sbs[(reg64.bits32.low >> 21) & 0x7]);
    }
  else
    {
      printf("Frequency Configuration, status is not available\n");
    }

  /* Enable flags */
  ret = read(DevPMC, &reg64, PMC_READ_MISC_ENABLE);
  if (ret == 8)
    {
      printf("Enable Flags:\n");
      if (!reg64.bits32.low) printf("  none\n");
      if (reg64.bits32.low & (1 << 0))
         printf("  fast strings feature\n");
      if (reg64.bits32.low & (1 << 2))
         printf("  x87 FPU Fopcode compatibility mode\n");
      if (reg64.bits32.low & (1 << 3))
         printf("  thermal monitor\n");
      if (reg64.bits32.low & (1 << 4))
         printf("  split-Lock disabled\n");
      if (reg64.bits32.low & (1 << 7))
         printf("  performance monitoring\n");
      if (reg64.bits32.low & (1 << 11))
         printf("  branch trace storage unavailable\n");
      if (reg64.bits32.low & (1 << 12))
         printf("  precise event-based sampling unavailable\n");
    }
  else
    {
      printf("Enable Flags, status is not available\n");
    }
#endif	/* PMC_P15 */


#ifdef PMC_TEST

  printf("\nPMC read tests\n\n");

#define R(choice,fmt,dest) \
  if ((ret = read(DevPMC, &dest, PMC_READ_ ## choice)) == sizeof(dest)) \
    { printf("read  PMC_READ_%-15s" fmt "\n", #choice, dest); } \
  else \
    { printf("read  PMC_READ_%-15sfailed, returned %d\n", #choice, ret); }

  R(CR0,fmt8,reg32);
  R(CR2,fmt8,reg32);
  R(CR3,fmt8,reg32);
  R(CR4,fmt8,reg32);

  R(TSC,fmt16,reg64.bits64);

#if defined(PMC_P5) || defined(PMC_P6) || defined(PMC_K7)
  R(0,fmt16,reg64.bits64);
  R(1,fmt16,reg64.bits64);
#if defined(PMC_K7)
  R(2,fmt16,reg64.bits64);
  R(3,fmt16,reg64.bits64);
#endif

  if ((ret = read(DevPMC, reg, PMC_READ)) == sizeof(reg))
    {
      printf("read  PMC_READ                0x%016llx\n", reg[0].bits64);
      for (i = 0; i < pmc_event_counters; i++) {
      printf("                              0x%016llx\n", reg[i+1].bits64);
      }
    }
  else
    { printf("read  PMC_READ                failed, returned %d\n", ret); }

  R(CONTROL_0,fmt16,reg64.bits64);
  R(CONTROL_1,fmt16,reg64.bits64);
#if defined(PMC_K7)
  R(CONTROL_2,fmt16,reg64.bits64);
  R(CONTROL_3,fmt16,reg64.bits64);
#endif

  if ((ret = read(DevPMC, reg, PMC_READ_CONTROL)) == sizeof(reg))
    {
      printf("read  PMC_READ_CONTROL        0x%016llx\n", reg[1].bits64);
      for (i = 1; i < pmc_event_counters; i++) {
      printf("                              0x%016llx\n", reg[i+1].bits64);
      }
    }
  else
    { printf("read  PMC_READ_CONTROL        failed, returned %d\n", ret); }
#endif  /* PMC_P5 PMC_P6 PMC_K7 */
 
#if defined(PMC_P15)
  if ((ret = read(DevPMC, p15_reg, PMC_READ))
      == (1 + 18)*sizeof(pmc_uint64_t))
    {
      printf("read  PMC_READ                0x%016llx\n", p15_reg[0].bits64);
      print_p15_counters(&p15_reg[1]);
    }
  else
    { printf("read  PMC_READ                failed, returned %d\n", ret); }

  if ((ret = read(DevPMC, p15_reg, PMC_READ_P15_COUNTERS))
      == 18*sizeof(pmc_uint64_t))
    {
      printf("read  PMC_READ_P15_COUNTERS, counter registers\n");
      print_p15_counters(p15_reg);
    }
  else
    { printf("read  PMC_READ_P15_COUNTERS   failed, returned %d\n", ret); }

  if ((ret = read(DevPMC, p15_reg, PMC_READ_CONTROL))
      == (18 + 46)*sizeof(pmc_uint64_t))
    {
      printf("read  PMC_READ_CONTROL cccr\n");
      print_p15_cccrs(p15_reg);
      printf("read  PMC_READ_CONTROL escr\n");
      print_p15_escrs(&p15_reg[18]);
    }
  else
    { printf("read  PMC_READ_CONTROL        failed, returned %d\n", ret); }

  if ((ret = read(DevPMC, p15_reg, PMC_READ_P15_CCCRS))
      == 18*sizeof(pmc_uint64_t))
    {
      printf("read  PMC_READ_P15_CCCRS, Pentium-4 CCCR control registers\n");
      print_p15_cccrs(p15_reg);
    }
  else
    { printf("read  PMC_READ_P15_CCCRS      failed, returned %d\n", ret); }

  if ((ret = read(DevPMC, p15_reg, PMC_READ_P15_ESCRS))
      == 46*sizeof(pmc_uint64_t))
    {
      printf("read  PMC_READ_P15_ESCRS, Pentium-4 ESCR control registers\n");
      print_p15_escrs(p15_reg);
    }
  else
    { printf("read  PMC_READ_P15_ESCRS      failed, returned %d\n", ret); }
#endif  /* PMC_P15 */

#define W(choice,fmt,src) \
  if ((ret = write(DevPMC, &src, PMC_WRITE_ ## choice)) == \
				 PMC_WRITE_ ## choice) \
    { printf("write PMC_WRITE_%-14s" fmt "\n", #choice, src); } \
  else \
    { printf("write PMC_WRITE_%-14sfailed, returned %d\n", #choice, ret); }

#if defined(PMC_P5)
#define OP \
  W(0,fmt16,val.bits64); \
  W(1,fmt16,val.bits64); \
  /* W(TSC,fmt16,val.bits64); */ \
  R(TSC,fmt16,reg64.bits64); \
  R(0,fmt16,reg64.bits64); \
  R(1,fmt16,reg64.bits64); \
  printf("\n");

#define COP \
  W(CONTROL_0,fmt16,val.bits64); \
  R(TSC,fmt16,reg64.bits64); \
  R(CONTROL_0,fmt16,reg64.bits64); \
  printf("\n");
#endif

#if defined(PMC_P6)
#define OP \
  W(0,fmt16,val.bits64); \
  W(1,fmt16,val.bits64); \
  /* W(TSC,fmt16,val.bits64); */ \
  R(TSC,fmt16,reg64.bits64); \
  R(0,fmt16,reg64.bits64); \
  R(1,fmt16,reg64.bits64); \
  printf("\n");

#define COP \
  W(CONTROL_0,fmt16,val.bits64); \
  W(CONTROL_1,fmt16,val.bits64); \
  R(TSC,fmt16,reg64.bits64); \
  R(CONTROL_0,fmt16,reg64.bits64); \
  R(CONTROL_1,fmt16,reg64.bits64); \
  printf("\n");
#endif

#if defined(PMC_K7)
#define OP \
  W(0,fmt16,val.bits64); \
  W(1,fmt16,val.bits64); \
  W(2,fmt16,val.bits64); \
  W(3,fmt16,val.bits64); \
  /* W(TSC,fmt16,val.bits64); */ \
  R(TSC,fmt16,reg64.bits64); \
  R(0,fmt16,reg64.bits64); \
  R(1,fmt16,reg64.bits64); \
  R(2,fmt16,reg64.bits64); \
  R(3,fmt16,reg64.bits64); \
  printf("\n");

#define COP \
  W(CONTROL_0,fmt16,val.bits64); \
  W(CONTROL_1,fmt16,val.bits64); \
  W(CONTROL_2,fmt16,val.bits64); \
  W(CONTROL_3,fmt16,val.bits64); \
  R(TSC,fmt16,reg64.bits64); \
  R(CONTROL_0,fmt16,reg64.bits64); \
  R(CONTROL_1,fmt16,reg64.bits64); \
  R(CONTROL_2,fmt16,reg64.bits64); \
  R(CONTROL_3,fmt16,reg64.bits64); \
  printf("\n");
#endif

#if defined(PMC_P15)
/* begin unfinished */
#define OP \
  for (i = 0; i < 18; i++) { p15_reg[i] = val; } \
  if ((ret = write(DevPMC, p15_reg, PMC_WRITE_P15_COUNTERS)) \
      != 18*sizeof(pmc_uint64_t)) \
    { printf("read  PMC_WRITE_P15_COUNTERS   failed, returned %d\n", ret); } \
  R(TSC,fmt16,reg64.bits64); \
  if ((ret = read(DevPMC, p15_reg, PMC_READ_P15_COUNTERS)) \
      == 18*sizeof(pmc_uint64_t)) \
    { \
      printf("read  PMC_READ_P15_COUNTERS, counter registers\n"); \
      print_p15_counters(p15_reg); \
    } \
  else \
    { printf("read  PMC_READ_P15_COUNTERS   failed, returned %d\n", ret); } \
  printf("\n");

#define COP \
  for (i = 0; i < 18+46; i++) { p15_reg[i] = val; } \
  if ((ret = write(DevPMC, p15_reg, PMC_WRITE_CONTROL)) \
      != (18+46)*sizeof(pmc_uint64_t)) \
    { printf("read  PMC_WRITE_CONTROL    failed, returned %d\n", ret); } \
  R(TSC,fmt16,reg64.bits64); \
  if ((ret = read(DevPMC, p15_reg, PMC_READ_CONTROL)) \
      == (18+46)*sizeof(pmc_uint64_t)) \
    { \
      printf("read  PMC_READ_P15_CCCRS, control registers\n"); \
      print_p15_cccrs(p15_reg); \
      printf("read  PMC_READ_P15_ESCRS, control registers\n"); \
      print_p15_escrs(&p15_reg[18]); \
    } \
  else \
    { printf("read  PMC_READ_CONTROL   failed, returned %d\n", ret); } \
  printf("\n");
/* end unfinished */
#endif	/* PMC_P15 */

  printf("\nPMC write tests\n\n");

  val.bits64 = 0x0000000012345678LL;
  OP;

  val.bits64 = 0x0000000087654321LL;	/* sign extension? */
  OP;

  val.bits64 = 0x8765432112345678LL;
  OP;

  val.bits64 = 0x1234567887654321LL;	/* sign extension? */
  OP;

  val.bits64 = 0xffffffffffffffffLL;	/* sign extension? */
  OP;

  val.bits64 = 0x0LL;			/* reset counters */
  OP;


  printf("\nPMC control write tests\n\n");

  val.bits64 = 0x0000000012345678LL;
  COP;

  val.bits64 = 0x0000000087654321LL;	/* sign extension? */
  COP;

  val.bits64 = 0x8765432112345678LL;
  COP;

  val.bits64 = 0x1234567887654321LL;	/* sign extension? */
  COP;

  val.bits64 = 0xffffffffffffffffLL;	/* reserved bits? */
  COP;

  val.bits64 = 0x0LL;			/* reset control */
  COP;

  val.bits64 = 0x0LL;			/* reset counters */
  OP;

#ifdef PMC_ALLOW_SYSTEM_TEST
  printf("\nPMC timing tests, serialized, with measurement overhead subtracted\n\n");

  for (i = 0; i < sizeof(test_code)/sizeof(test_code[0]); i++)
    {
      printf("  cycles for %20s =", test_name[i]);
      for (j = 0; j < 7; j++)
	{
	  ret = (int) lseek(DevPMC, test_code[i], SEEK_SET);
	  if (ret < 0)
            { printf("   ?"); }
	  else
            { printf(" %3d", ret); }
	}
      printf("\n");
    }
#endif	/* PMC_ALLOW_SYSTEM_TEST */

#endif	/* PMC_TEST */

  if (close(DevPMC) == -1)
    { printf("/dev/pmc failed to close: %s", strerror(errno)); }

  exit(0);
}

/*----------------------------------------------------------------------------*/

void print_p15_counters(pmc_uint64_t reg[18])
{
  printf("      BPU_COUNTER0            0x%016llx\n", reg[0].bits64);
  printf("      BPU_COUNTER1            0x%016llx\n", reg[1].bits64);
  printf("      BPU_COUNTER2            0x%016llx\n", reg[2].bits64);
  printf("      BPU_COUNTER3            0x%016llx\n", reg[3].bits64);
  printf("      MS_COUNTER0             0x%016llx\n", reg[4].bits64);
  printf("      MS_COUNTER1             0x%016llx\n", reg[5].bits64);
  printf("      MS_COUNTER2             0x%016llx\n", reg[6].bits64);
  printf("      MS_COUNTER3             0x%016llx\n", reg[7].bits64);
  printf("      FLAME_COUNTER0          0x%016llx\n", reg[8].bits64);
  printf("      FLAME_COUNTER1          0x%016llx\n", reg[9].bits64);
  printf("      FLAME_COUNTER2          0x%016llx\n", reg[10].bits64);
  printf("      FLAME_COUNTER3          0x%016llx\n", reg[11].bits64);
  printf("      IQ_COUNTER0             0x%016llx\n", reg[12].bits64);
  printf("      IQ_COUNTER1             0x%016llx\n", reg[13].bits64);
  printf("      IQ_COUNTER2             0x%016llx\n", reg[14].bits64);
  printf("      IQ_COUNTER3             0x%016llx\n", reg[15].bits64);
  printf("      IQ_COUNTER4             0x%016llx\n", reg[16].bits64);
  printf("      IQ_COUNTER5             0x%016llx\n", reg[17].bits64);
  return;
}

void print_p15_cccrs(pmc_uint64_t reg[18])
{
  printf("      BPU_CCCR0               0x%016llx\n", reg[0].bits64);
  printf("      BPU_CCCR1               0x%016llx\n", reg[1].bits64);
  printf("      BPU_CCCR2               0x%016llx\n", reg[2].bits64);
  printf("      BPU_CCCR3               0x%016llx\n", reg[3].bits64);
  printf("      MS_CCCR0                0x%016llx\n", reg[4].bits64);
  printf("      MS_CCCR1                0x%016llx\n", reg[5].bits64);
  printf("      MS_CCCR2                0x%016llx\n", reg[6].bits64);
  printf("      MS_CCCR3                0x%016llx\n", reg[7].bits64);
  printf("      FLAME_CCCR0             0x%016llx\n", reg[8].bits64);
  printf("      FLAME_CCCR1             0x%016llx\n", reg[9].bits64);
  printf("      FLAME_CCCR2             0x%016llx\n", reg[10].bits64);
  printf("      FLAME_CCCR3             0x%016llx\n", reg[11].bits64);
  printf("      IQ_CCCR0                0x%016llx\n", reg[12].bits64);
  printf("      IQ_CCCR1                0x%016llx\n", reg[13].bits64);
  printf("      IQ_CCCR2                0x%016llx\n", reg[14].bits64);
  printf("      IQ_CCCR3                0x%016llx\n", reg[15].bits64);
  printf("      IQ_CCCR4                0x%016llx\n", reg[16].bits64);
  printf("      IQ_CCCR5                0x%016llx\n", reg[17].bits64);
  return;
}

void print_p15_escrs(pmc_uint64_t reg[46])
{
  printf("      BSU_ESCR0               0x%016llx\n", reg[0].bits64);
  printf("      BSU_ESCR1               0x%016llx\n", reg[1].bits64);
  printf("      FSB_ESCR0               0x%016llx\n", reg[2].bits64);
  printf("      FSB_ESCR1               0x%016llx\n", reg[3].bits64);
  printf("      FIRM_ESCR0              0x%016llx\n", reg[4].bits64);
  printf("      FIRM_ESCR1              0x%016llx\n", reg[5].bits64);
  printf("      FLAME_ESCR0             0x%016llx\n", reg[6].bits64);
  printf("      FLAME_ESCR1             0x%016llx\n", reg[7].bits64);
  printf("      DAC_ESCR0               0x%016llx\n", reg[8].bits64);
  printf("      DAC_ESCR1               0x%016llx\n", reg[9].bits64);
  printf("      MOB_ESCR0               0x%016llx\n", reg[10].bits64);
  printf("      MOB_ESCR1               0x%016llx\n", reg[11].bits64);
  printf("      PMH_ESCR0               0x%016llx\n", reg[12].bits64);
  printf("      PMH_ESCR1               0x%016llx\n", reg[13].bits64);
  printf("      SAAT_ESCR0              0x%016llx\n", reg[14].bits64);
  printf("      SAAT_ESCR1              0x%016llx\n", reg[15].bits64);
  printf("      U2L_ESCR0               0x%016llx\n", reg[16].bits64);
  printf("      U2L_ESCR1               0x%016llx\n", reg[17].bits64);
  printf("      BPU_ESCR0               0x%016llx\n", reg[18].bits64);
  printf("      BPU_ESCR1               0x%016llx\n", reg[19].bits64);
  printf("      IS_ESCR0                0x%016llx\n", reg[20].bits64);
  printf("      IS_ESCR1                0x%016llx\n", reg[21].bits64);
  printf("      ITLB_ESCR0              0x%016llx\n", reg[22].bits64);
  printf("      ITLB_ESCR1              0x%016llx\n", reg[23].bits64);
  printf("      CRU_ESCR0               0x%016llx\n", reg[24].bits64);
  printf("      CRU_ESCR1               0x%016llx\n", reg[25].bits64);
  printf("      IQ_ESCR0                0x%016llx\n", reg[26].bits64);
  printf("      IQ_ESCR1                0x%016llx\n", reg[27].bits64);
  printf("      RAT_ESCR0               0x%016llx\n", reg[28].bits64);
  printf("      RAT_ESCR1               0x%016llx\n", reg[29].bits64);
  printf("      SSU_ESCR0               0x%016llx\n", reg[30].bits64);
//printf("      SSU_ESCR1               0x%016llx\n", reg[31].bits64);
	/* SSU_ESCR1 is not implemented */
  printf("      MS_ESCR0                0x%016llx\n", reg[32].bits64);
  printf("      MS_ESCR1                0x%016llx\n", reg[33].bits64);
  printf("      TBPU_ESCR0              0x%016llx\n", reg[34].bits64);
  printf("      TBPU_ESCR1              0x%016llx\n", reg[35].bits64);
  printf("      TC_ESCR0                0x%016llx\n", reg[36].bits64);
  printf("      TC_ESCR1                0x%016llx\n", reg[37].bits64);
  printf("      IX_ESCR0                0x%016llx\n", reg[38].bits64);
  printf("      IX_ESCR1                0x%016llx\n", reg[39].bits64);
  printf("      ALF_ESCR0               0x%016llx\n", reg[40].bits64);
  printf("      ALF_ESCR1               0x%016llx\n", reg[41].bits64);
  printf("      CRU_ESCR2               0x%016llx\n", reg[42].bits64);
  printf("      CRU_ESCR3               0x%016llx\n", reg[43].bits64);
  printf("      CRU_ESCR4               0x%016llx\n", reg[44].bits64);
  printf("      CRU_ESCR5               0x%016llx\n", reg[45].bits64);
  return;
}

/*----------------------------------------------------------------------------*/
