/*
 * Copyright (C) 2007-2014 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#define FAST

#define XCONC(a, b, c)  a ## _ ## b ## _ ## c
#define CONC(a, b, c)   XCONC(a, b, c)

#include <assert.h>
#include <setjmp.h>
#include <stdio.h>

#include "glue-main.h"
#include "glue-floatx.h"

#include "chip_intel_80686_coppermine_def.h"

#include "arch_gen_cpu_x86_state.h"

void
chip_intel_80686_coppermine_helper_cpuid(struct cpssp *cpssp)
{
	uint32_t index_;

	index_ = (uint32_t) cpssp->regs[R_EAX];

	if (2 < index_) {
		index_ = 0;
	}

	switch (index_) {
	case 0:
		cpssp->regs[R_EAX] = 2;
		cpssp->regs[R_EBX] = 0x756e6547; /* "GenuineIntel" */
		cpssp->regs[R_ECX] = 0x6c65746e;
		cpssp->regs[R_EDX] = 0x49656e69;
		break;
	case 1:
		cpssp->regs[R_EAX] = 0x00000686; /* CPU Version */
		cpssp->regs[R_EBX] = 0x00000002;
		cpssp->regs[R_ECX] = 0x00000000;
		cpssp->regs[R_EDX] = CONFIG_CPU_FPU_SUPPORT << 0
			| CONFIG_CPU_VME_SUPPORT << 1
			| CONFIG_CPU_DE_SUPPORT << 2
			| CONFIG_CPU_PSE_SUPPORT << 3
			| CONFIG_CPU_TSC_SUPPORT << 4
			| CONFIG_CPU_MSR_SUPPORT << 5
			| CONFIG_CPU_PAE_SUPPORT << 6
			| CONFIG_CPU_MCE_SUPPORT << 7
			| CONFIG_CPU_CX8_SUPPORT << 8
			| CONFIG_CPU_APIC_SUPPORT << 9
			| CONFIG_CPU_SEP_SUPPORT << 11 
			| CONFIG_CPU_MTRR_SUPPORT << 12
			| CONFIG_CPU_PGE_SUPPORT << 13
			| CONFIG_CPU_MCA_SUPPORT << 14
			| CONFIG_CPU_CMOV_SUPPORT << 15
			| CONFIG_CPU_PAT_SUPPORT << 16
			| CONFIG_CPU_PSE36_SUPPORT << 17
			| CONFIG_CPU_PSN_SUPPORT << 18
			| CONFIG_CPU_CFLSH_SUPPORT << 19
			| CONFIG_CPU_DS_SUPPORT << 21
			| CONFIG_CPU_ACPI_SUPPORT << 22
			| CONFIG_CPU_MMX_SUPPORT << 23
			| CONFIG_CPU_FXSR_SUPPORT << 24
			| CONFIG_CPU_SSE_SUPPORT << 25
			| CONFIG_CPU_SSE2_SUPPORT << 26
			| CONFIG_CPU_SS_SUPPORT << 27
			| CONFIG_CPU_HTT_SUPPORT << 28
			| CONFIG_CPU_TM_SUPPORT << 29
			| CONFIG_CPU_PBE_SUPPORT << 31;

		cpssp->update_signature = 0;
		break;
	case 2:
		cpssp->regs[R_EAX] = (0x03 << 24) /* Data TLB, 4K pages, 4 ways, 64 entries */
		    | (0x02 << 16) /* code TLB, 4M pages, fully, 2 entries */
		    | (0x01 << 8) /* code TLB, 4K pages, 4 ways, 32 entries */
		    | (0x01 << 0); /* call cpuid once */
		cpssp->regs[R_EBX] = 0x00000000;
		cpssp->regs[R_ECX] = 0x00000000;
		cpssp->regs[R_EDX] = (0x0c << 24) /* data L1 cache, 16KB, 4 ways, 32B lines */
		    | (0x04 << 16) /* data TLB, 4M pages, 4 ways, 8 entries */
		    | (0x08 << 8) /* code L1 cache, 16KB, 4 ways, 32B lines */
		    | (0x82 << 0); /* c/d L2 cache, 256KB, 8 ways, 32B lines */
		break;
	default:
		assert(0); /* Cannot happen. */
	}
}
