/*
 * Copyright (c) 2006, 2007 Advanced Micro Devices, Inc.
 * Contributed by Ray Bryant <raybry@mpdtxmail.amd.com>
 * Contributed by Robert Richter <robert.richter@amd.com>
 * Modified for K7 by Vince Weaver <vince _at_ csl.cornell.edu>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * This file is part of libpfm, a performance monitoring support library for
 * applications on Linux.
 */

/*
 * Definitions taken from "AMD Athlon Processor x86 Code Optimization Guide"
 * Table 11 February 2002
 */

static pme_amd64_entry_t amd64_k7_pe[]={
/*  0 */{.pme_name = "DATA_CACHE_ACCESSES",
	.pme_code  = 0x40,
	.pme_desc  = "Data Cache Accesses",
	},
/*  1 */{.pme_name = "DATA_CACHE_MISSES",
	.pme_code  = 0x41,
	.pme_desc  = "Data Cache Misses",
	},
/*  2 */{.pme_name = "DATA_CACHE_REFILLS",
	.pme_code  = 0x42,
	.pme_desc  = "Data Cache Refills from L2",
	.pme_flags = PFMLIB_AMD64_UMASK_COMBO,
	.pme_numasks = 6,
	.pme_umasks  = {
		{ .pme_uname = "L2_INVALID",
		  .pme_udesc = "Invalid line from L2",
		  .pme_ucode = 0x01,
		},
		{ .pme_uname = "L2_SHARED",
		  .pme_udesc = "Shared-state line from L2",
		  .pme_ucode = 0x02,
		},
		{ .pme_uname = "L2_EXCLUSIVE",
		  .pme_udesc = "Exclusive-state line from L2",
		  .pme_ucode = 0x04,
		},
		{ .pme_uname = "L2_OWNED",
		  .pme_udesc = "Owned-state line from L2",
		  .pme_ucode = 0x08,
		},
		{ .pme_uname = "L2_MODIFIED",
		  .pme_udesc = "Modified-state line from L2",
		  .pme_ucode = 0x10,
		},
		{ .pme_uname = "ALL",
		  .pme_udesc = "Shared, Exclusive, Owned, Modified State Refills",
		  .pme_ucode = 0x1F,
		},
	 },
	},
/*  3 */{.pme_name = "DATA_CACHE_REFILLS_FROM_SYSTEM",
	.pme_code  = 0x43,
	.pme_desc  = "Data Cache Refills from System",
	.pme_flags = PFMLIB_AMD64_UMASK_COMBO,
	.pme_numasks = 6,
	.pme_umasks  = {
		{ .pme_uname = "INVALID",
		  .pme_udesc = "Invalid",
		  .pme_ucode = 0x01,
		},
		{ .pme_uname = "SHARED",
		  .pme_udesc = "Shared",
		  .pme_ucode = 0x02,
		},
		{ .pme_uname = "EXCLUSIVE",
		  .pme_udesc = "Exclusive",
		  .pme_ucode = 0x04,
		},
		{ .pme_uname = "OWNED",
		  .pme_udesc = "Owned",
		  .pme_ucode = 0x08,
		},
		{ .pme_uname = "MODIFIED",
		  .pme_udesc = "Modified",
		  .pme_ucode = 0x10,
		},
		{ .pme_uname = "ALL",
		  .pme_udesc = "Invalid, Shared, Exclusive, Owned, Modified",
		  .pme_ucode = 0x1F,
		},
	 },
	},
/*  4 */{.pme_name = "DATA_CACHE_LINES_EVICTED",
	.pme_code  = 0x44,
	.pme_desc  = "Data Cache Lines Evicted",
	.pme_flags = PFMLIB_AMD64_UMASK_COMBO,
	.pme_numasks = 6,
	.pme_umasks  = {
		{ .pme_uname = "INVALID",
		  .pme_udesc = "Invalid",
		  .pme_ucode = 0x01,
		},
		{ .pme_uname = "SHARED",
		  .pme_udesc = "Shared",
		  .pme_ucode = 0x02,
		},
		{ .pme_uname = "EXCLUSIVE",
		  .pme_udesc = "Exclusive",
		  .pme_ucode = 0x04,
		},
		{ .pme_uname = "OWNED",
		  .pme_udesc = "Owned",
		  .pme_ucode = 0x08,
		},
		{ .pme_uname = "MODIFIED",
		  .pme_udesc = "Modified",
		  .pme_ucode = 0x10,
		},
		{ .pme_uname = "ALL",
		  .pme_udesc = "Invalid, Shared, Exclusive, Owned, Modified",
		  .pme_ucode = 0x1F,
		},
	 },
	},
/*  5 */{.pme_name = "L1_DTLB_MISS_AND_L2_DTLB_HIT",
	.pme_code  = 0x45,
	.pme_desc  = "L1 DTLB Miss and L2 DTLB Hit",
	},
/*  6 */{.pme_name = "L1_DTLB_AND_L2_DTLB_MISS",
	.pme_code  = 0x46,
	.pme_desc  = "L1 DTLB and L2 DTLB Miss",
	},
/*  7 */{.pme_name = "MISALIGNED_ACCESSES",
	.pme_code  = 0x47,
	.pme_desc  = "Misaligned Accesses",
       },
        /* CPU_CLK_UNHALTED is undocumented in the Athlon Guide? */
/*  8 */{.pme_name = "CPU_CLK_UNHALTED",
        .pme_code  = 0x76,
        .pme_desc  = "CPU Clocks not Halted",
        },
/*  9 */{.pme_name = "INSTRUCTION_CACHE_FETCHES",
	.pme_code  = 0x80,
	.pme_desc  = "Instruction Cache Fetches",
	},
/* 10 */{.pme_name = "INSTRUCTION_CACHE_MISSES",
	.pme_code  = 0x81,
	.pme_desc  = "Instruction Cache Misses",
	},
/* 11 */{.pme_name = "L1_ITLB_MISS_AND_L2_ITLB_HIT",
	.pme_code  = 0x84,
	.pme_desc  = "L1 ITLB Miss and L2 ITLB Hit",
	},
/* 12 */{.pme_name = "L1_ITLB_MISS_AND_L2_ITLB_MISS",
	.pme_code  = 0x85,
	.pme_desc  = "L1 ITLB Miss and L2 ITLB Miss",
	},
/* 13 */{.pme_name = "RETIRED_INSTRUCTIONS",
	.pme_code  = 0xC0,
	.pme_desc  = "Retired Instructions (includes exceptions, interrupts, resyncs)",
	},
/* 14 */{.pme_name = "RETIRED_UOPS",
	.pme_code  = 0xC1,
	.pme_desc  = "Retired uops",
	},
/* 15 */{.pme_name = "RETIRED_BRANCH_INSTRUCTIONS",
         .pme_code  = 0xC2,
	.pme_desc  = "Retired Branch Instructions",
	},
/* 16 */{.pme_name = "RETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS",
	.pme_code  = 0xC3,
	.pme_desc  = "Retired Mispredicted Branch Instructions",
	},
/* 17 */{.pme_name = "RETIRED_TAKEN_BRANCH_INSTRUCTIONS",
	.pme_code  = 0xC4,
	.pme_desc  = "Retired Taken Branch Instructions",
	},
/* 18 */{.pme_name = "RETIRED_TAKEN_BRANCH_INSTRUCTIONS_MISPREDICTED",
	.pme_code  = 0xC5,
	.pme_desc  = "Retired Taken Branch Instructions Mispredicted",
	},
/* 19 */{.pme_name = "RETIRED_FAR_CONTROL_TRANSFERS",
	.pme_code  = 0xC6,
	.pme_desc  = "Retired Far Control Transfers",
	},
/* 20 */{.pme_name = "RETIRED_BRANCH_RESYNCS",
	.pme_code  = 0xC7,
	.pme_desc  = "Retired Branch Resyncs (only non-control transfer branches)",
	},
/* 21 */{.pme_name = "INTERRUPTS_MASKED_CYCLES",
	.pme_code  = 0xCD,
	.pme_desc  = "Interrupts-Masked Cycles",
	},
/* 22 */{.pme_name = "INTERRUPTS_MASKED_CYCLES_WITH_INTERRUPT_PENDING",
	.pme_code  = 0xCE,
	.pme_desc  = "Interrupts-Masked Cycles with Interrupt Pending",
	},
/* 23 */{.pme_name = "INTERRUPTS_TAKEN",
	.pme_code  = 0xCF,
	.pme_desc  = "Interrupts Taken",
	},
};

#define PME_AMD64_K7_EVENT_COUNT		(sizeof(amd64_k7_pe)/sizeof(pme_amd64_entry_t))
#define PME_AMD64_K7_CPU_CLK_UNHALTED		8
#define PME_AMD64_K7_RETIRED_INSTRUCTIONS	13
