
#include <stdio.h>
#include <stdlib.h>

unsigned long long pte_va(unsigned long long pte0, unsigned long hash);

static unsigned long long htonll(unsigned long long val);

static void usage(char *progname);

/*
 * main
 */
int main(int argc, char **argv)
{
	FILE *fp;
	long offset;
	int entries, i;
	unsigned long long pte[2];

	if (argc != 4)
		usage(argv[0]);

	fp = fopen(argv[1], "r");
	if (fp == NULL)
	{
		fprintf(stderr, "couldn't open file: '%s'\n", argv[1]);
		exit(1);
	}

	offset = strtol(argv[2], NULL, 0);
	entries = strtol(argv[3], NULL, 0);

	fseek(fp, offset, SEEK_SET);

	for (i = 0; i < entries; i++)
	{
		fread(pte, sizeof(unsigned long long), 2, fp);

		pte[0] = htonll(pte[0]);
		pte[1] = htonll(pte[1]);

		if ((i != 0) && (i % 8 == 0))
			printf("\n");

		printf("PTE=(0x%016llx, 0x%016llx) -- V=%d L=%d H=%d SW=0x%x N=%d PP=0x%x -- "
			"0x%016llx 0x%016llx -- 0x%016llx\n",
			pte[0], pte[1],
			(int) (pte[0] & 0x1), (int) (!!(pte[0] & 0x4)), (int) (!!(pte[0] & 0x2)), (int) ((pte[0] & 0x78) >> 3),
			(int) (!!(pte[1] & 0x4)), (int) (pte[1] & 0x3),
			(pte[0] >> 7) << 23, (pte[1] >> 12) << 12,
			pte_va(pte[0], i / 8));
	}

	fclose(fp);

	exit(0);
}

/*
 * pte_va
 */
unsigned long long pte_va(unsigned long long pte0, unsigned long hash)
{
	return ((((pte0 >> 7) >> 5) ^ hash) << 12) | ((pte0 >> 7) << 23);
}

/*
 * htonll
 */
static unsigned long long htonll(unsigned long long val)
{
	return (((unsigned long long) htonl(val & 0xffffffff)) << 32) |
		((unsigned long long) htonl(val >> 32));
}

/*
 * usage
 */
static void usage(char *progname)
{
	fprintf(stderr, "usage: %s <HV dump> <HTAB offset> <HTAB entries>\n");
	exit(1);
}
