#ifndef PMC_ARCH_H
#define PMC_ARCH_H

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

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

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

	/* processor architecture */

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

/* Has the architecture been defined uniquely? */

#define PMC_ARCH_0 0

#if defined(PMC_P5)
#define PMC_ARCH_1 (PMC_ARCH_0 + 1)
#else
#define PMC_ARCH_1 (PMC_ARCH_0 + 0)
#endif

#if defined(PMC_P6)
#define PMC_ARCH_2 (PMC_ARCH_1 + 1)
#else
#define PMC_ARCH_2 (PMC_ARCH_1 + 0)
#endif

#if defined(PMC_P15)
#define PMC_ARCH_3 (PMC_ARCH_2 + 1)
#else
#define PMC_ARCH_3 (PMC_ARCH_2 + 0)
#endif

#if defined(PMC_K7)
#define PMC_ARCH_4 (PMC_ARCH_3 + 1)
#else
#define PMC_ARCH_4 (PMC_ARCH_3 + 0)
#endif

#define PMC_ARCH PMC_ARCH_4

#if (PMC_ARCH == 0)
#error --- architecture not defined
#endif

#if (PMC_ARCH > 1)
#error --- architecture not uniquely defined
#endif

#undef PMC_ARCH_0
#undef PMC_ARCH_1
#undef PMC_ARCH_2
#undef PMC_ARCH_3
#undef PMC_ARCH_4
#undef PMC_ARCH

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

/*
 * Intel Pentium-series and AMD Athlon model-specific registers
 *
 *   PMC_TSC			Time stamp (cycle) counter
 *   PMC_[01]			Performance-monitoring (event) counters
 *   PMC_CONTROL_[01]		Control register(s) for PMC_[01]
 *   pmc_event_counters		number of event counters
 *   pmc_cycle_bits		number of bits in the cycle counter
 *   pmc_event_bits		number of bits in the event counter
 *   PMC_MESI_LIMIT		unit mask for P6, K7 control registers
 */

#if defined(PMC_P5)
#define PMC_TSC			0x10
#define PMC_0			0x12
#define PMC_1			0x13
#define PMC_CONTROL_0		0x11
   /* PMC_[23] and PMC_CONTROL_[123] must remain undefined */
#define pmc_event_counters	2
#define pmc_cycle_bits		64
#define pmc_event_bits		40
#endif	/* PMC_P5 */

#if defined(PMC_P6)
#define PMC_TSC			0x10
#define PMC_0			0xC1
#define PMC_1			0xC2
#define PMC_CONTROL_0		0x186
#define PMC_CONTROL_1		0x187
   /* PMC_[23] and PMC_CONTROL_[23] must remain undefined */
#define pmc_event_counters	2
#define pmc_cycle_bits		64
#define pmc_event_bits		40
#endif	/* PMC_P6 */

#if defined(PMC_K7)
#define PMC_TSC			0x10
#define PMC_0			0xC0010004
#define PMC_1			0xC0010005
#define PMC_2			0xC0010006
#define PMC_3			0xC0010007
#define PMC_CONTROL_0		0xC0010000
#define PMC_CONTROL_1		0xC0010001
#define PMC_CONTROL_2		0xC0010002
#define PMC_CONTROL_3		0xC0010003
#define pmc_event_counters	4
#define pmc_cycle_bits		64
#define pmc_event_bits		48
#endif	/* PMC_K7 */

#if defined(PMC_P15)
#define PMC_TSC			0x10
#define pmc_event_counters	2
   /* unfinished - there are actually 18 counters */
#define pmc_cycle_bits		64
#define pmc_event_bits		40

/* 18 performance counter registers, 0x300 through 0x311 */
#define PMC_BPU_COUNTER0	0x300
#define PMC_BPU_COUNTER1	0x301
#define PMC_BPU_COUNTER2	0x302
#define PMC_BPU_COUNTER3	0x303
#define PMC_MS_COUNTER0		0x304
#define PMC_MS_COUNTER1		0x305
#define PMC_MS_COUNTER2		0x306
#define PMC_MS_COUNTER3		0x307
#define PMC_FLAME_COUNTER0	0x308
#define PMC_FLAME_COUNTER1	0x309
#define PMC_FLAME_COUNTER2	0x30a
#define PMC_FLAME_COUNTER3	0x30b
#define PMC_IQ_COUNTER0		0x30c
#define PMC_IQ_COUNTER1		0x30d
#define PMC_IQ_COUNTER2		0x30e
#define PMC_IQ_COUNTER3		0x30f
#define PMC_IQ_COUNTER4		0x310
#define PMC_IQ_COUNTER5		0x311

/* 18 counter configuration control registers, 0x360 through 0x371 */
#define PMC_BPU_CCCR0		0x360
#define PMC_BPU_CCCR1		0x361
#define PMC_BPU_CCCR2		0x362
#define PMC_BPU_CCCR3		0x363
#define PMC_MS_CCCR0		0x364
#define PMC_MS_CCCR1		0x365
#define PMC_MS_CCCR2		0x366
#define PMC_MS_CCCR3		0x367
#define PMC_FLAME_CCCR0		0x368
#define PMC_FLAME_CCCR1		0x369
#define PMC_FLAME_CCCR2		0x36a
#define PMC_FLAME_CCCR3		0x36b
#define PMC_IQ_CCCR0		0x36c
#define PMC_IQ_CCCR1		0x36d
#define PMC_IQ_CCCR2		0x36e
#define PMC_IQ_CCCR3		0x36f
#define PMC_IQ_CCCR4		0x370
#define PMC_IQ_CCCR5		0x371

/* 45 event selection control registers, 0x3a0 through 0x3e1
 *	except 0x3bf, 0x3c6, 0x3c7, 0x3ce, 0x3cf, 0x3d[0-f]
 */
#define PMC_BSU_ESCR0		0x3a0
#define PMC_BSU_ESCR1		0x3a1
#define PMC_FSB_ESCR0		0x3a2
#define PMC_FSB_ESCR1		0x3a3
#define PMC_FIRM_ESCR0		0x3a4
#define PMC_FIRM_ESCR1		0x3a5
#define PMC_FLAME_ESCR0		0x3a6
#define PMC_FLAME_ESCR1		0x3a7
#define PMC_DAC_ESCR0		0x3a8
#define PMC_DAC_ESCR1		0x3a9
#define PMC_MOB_ESCR0		0x3aa
#define PMC_MOB_ESCR1		0x3ab
#define PMC_PMH_ESCR0		0x3ac
#define PMC_PMH_ESCR1		0x3ad
#define PMC_SAAT_ESCR0		0x3ae
#define PMC_SAAT_ESCR1		0x3af

#define PMC_U2L_ESCR0		0x3b0
#define PMC_U2L_ESCR1		0x3b1
#define PMC_BPU_ESCR0		0x3b2
#define PMC_BPU_ESCR1		0x3b3
#define PMC_IS_ESCR0		0x3b4
#define PMC_IS_ESCR1		0x3b5
#define PMC_ITLB_ESCR0		0x3b6
#define PMC_ITLB_ESCR1		0x3b7
#define PMC_CRU_ESCR0		0x3b8
#define PMC_CRU_ESCR1		0x3b9
#define PMC_IQ_ESCR0		0x3ba
#define PMC_IQ_ESCR1		0x3bb
#define PMC_RAT_ESCR0		0x3bc
#define PMC_RAT_ESCR1		0x3bd
#define PMC_SSU_ESCR0		0x3be
#define PMC_SSU_ESCR1		0x3bf	/* not implemented */

#define PMC_MS_ESCR0		0x3c0
#define PMC_MS_ESCR1		0x3c1
#define PMC_TBPU_ESCR0		0x3c2
#define PMC_TBPU_ESCR1		0x3c3
#define PMC_TC_ESCR0		0x3c4
#define PMC_TC_ESCR1		0x3c5
#define PMC_UNKNOWN_3c6		0x3c6	/* not implemented */
#define PMC_UNKNOWN_3c7		0x3c7	/* not implemented */
#define PMC_IX_ESCR0		0x3c8
#define PMC_IX_ESCR1		0x3c9
#define PMC_ALF_ESCR0		0x3ca
#define PMC_ALF_ESCR1		0x3cb
#define PMC_CRU_ESCR2		0x3cc
#define PMC_CRU_ESCR3		0x3cd
#define PMC_UNKNOWN_3ce		0x3ce	/* not implemented */
#define PMC_UNKNOWN_3cf		0x3cf	/* not implemented */

#define PMC_UNKNOWN_3d0		0x3d0	/* not implemented */
#define PMC_UNKNOWN_3d1		0x3d1	/* not implemented */
#define PMC_UNKNOWN_3d2		0x3d2	/* not implemented */
#define PMC_UNKNOWN_3d3		0x3d3	/* not implemented */
#define PMC_UNKNOWN_3d4		0x3d4	/* not implemented */
#define PMC_UNKNOWN_3d5		0x3d5	/* not implemented */
#define PMC_UNKNOWN_3d6		0x3d6	/* not implemented */
#define PMC_UNKNOWN_3d7		0x3d7	/* not implemented */
#define PMC_UNKNOWN_3d8		0x3d8	/* not implemented */
#define PMC_UNKNOWN_3d9		0x3d9	/* not implemented */
#define PMC_UNKNOWN_3da		0x3da	/* not implemented */
#define PMC_UNKNOWN_3db		0x3db	/* not implemented */
#define PMC_UNKNOWN_3dc		0x3dc	/* not implemented */
#define PMC_UNKNOWN_3dd		0x3dd	/* not implemented */
#define PMC_UNKNOWN_3de		0x3de	/* not implemented */
#define PMC_UNKNOWN_3df		0x3df	/* not implemented */

#define PMC_CRU_ESCR4		0x3e0
#define PMC_CRU_ESCR5		0x3e1

/* additional controls */
#define PMC_TC_PRECISE_EVENT	0x3f0
#define PMC_PEBS_ENABLE		0x3f1
#endif	/* PMC_P15 */

#if defined(PMC_P6)		/* MESI protocol */
#define PMC_MESI_LIMIT 0xf
#endif

#if defined(PMC_K7)		/* MOESI protocol */
#define PMC_MESI_LIMIT 0x1f
#endif

#if defined(PMC_P15)		/* MESI protocol */
/* begin unfinished */
#define PMC_MESI_LIMIT 0xf
/* end unfinished */
#endif

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

/* Intel model-specific registers */

#if defined(PMC_P6)
#define PMC_APIC_BASE_MSR       0x1b
#endif

#if defined(PMC_P15)
#define PMC_APIC_BASE_MSR	0x1b
#define PMC_BUS_FREQUENCY_MSR	0x2c
#define PMC_MISC_ENABLE_MSR	0x1a0
#endif

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

/* Intel Pentium 4 */

#ifdef PMC_SSE2
#ifndef PMC_SSE
#define PMC_SSE
#endif
#endif	/* PMC_SSE2 */

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

/* Intel Pentium III/4 */

#ifdef PMC_SSE
#ifndef PMC_MMX
#define PMC_MMX
#endif
#endif	/* PMC_SSE */

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

/* The Intel time-stamp and event counters can be obtained by pmc_read()
 * through the rdmsr instruction in kernel mode, or through the rdtsc and
 * rdpmc instructions in user mode if certain permission bits are enabled
 * by the kernel.  The original Pentium does not have the rdpmc instruction,
 * so it must use rdmsr.
 */

#ifndef PMC_READ_KERNEL_MODE
#if defined(PMC_P5) && !defined(PMC_MMX)
#define PMC_READ_KERNEL_MODE
#endif
#endif	/* PMC_READ_KERNEL_MODE */

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

#endif	/* PMC_ARCH_H */
