/*
 * Copyright (C) 2009 David McPaul
 *
 * includes code from sysinfo.c which is
 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
 * Copyright (c) 2002, Carlos Hasan, for Haiku.
 *
 * All rights reserved. Distributed under the terms of the MIT License.
 */
 
 
#include "CpuCapabilities.h"
 
#include <string.h>
#include <cpu_type.h>
 
 
CPUCapabilities::~CPUCapabilities()
{
}
 
 
CPUCapabilities::CPUCapabilities()
	: fCapabilities(0)
{
#if defined(__i386__) || defined(__x86_64__)
	_SetIntelCapabilities();
#endif
}
 
 
#if defined(__i386__) || defined(__x86_64__)
void
CPUCapabilities::_SetIntelCapabilities()
{
	cpuid_info baseInfo;
	cpuid_info cpuInfo;
	int32 maxStandardFunction, maxExtendedFunction = 0;
 
	if (get_cpuid(&baseInfo, 0L, 0L) != B_OK) {
		// this CPU doesn't support cpuid
		return;
	}
 
	maxStandardFunction = baseInfo.eax_0.max_eax;
	if (maxStandardFunction >= 500) {
		maxStandardFunction = 0; /* old Pentium sample chips has cpu signature here */
	}
	
	/* Extended cpuid */
 
	get_cpuid(&cpuInfo, 0x80000000, 0L);
 
	// extended cpuid is only supported if max_eax is greater than the service id
	if (cpuInfo.eax_0.max_eax > 0x80000000) {
		maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
	}
	
	if (maxStandardFunction > 0) {
 
		get_cpuid(&cpuInfo, 1L, 0L);
		if (cpuInfo.eax_1.features & (1UL << 23)) {
			fCapabilities = CAPABILITY_MMX;
		}
	
		if (cpuInfo.eax_1.features & (1UL << 25)) {
			fCapabilities = CAPABILITY_SSE1;
		}
 
		if (cpuInfo.eax_1.features & (1UL << 26)) {
			fCapabilities = CAPABILITY_SSE2;
		}
 
		if (maxStandardFunction >= 1) {
			/* Extended features */
			if (cpuInfo.eax_1.extended_features & (1UL << 0)) {
				fCapabilities = CAPABILITY_SSE3;
			}
			if (cpuInfo.eax_1.extended_features & (1UL << 9)) {
				fCapabilities = CAPABILITY_SSSE3;
			}
			if (cpuInfo.eax_1.extended_features & (1UL << 19)) {
				fCapabilities = CAPABILITY_SSE41;
			}
			if (cpuInfo.eax_1.extended_features & (1UL << 20)) {
				fCapabilities = CAPABILITY_SSE42;
			}
		}
	}
}
#endif // __i386__ || __x86_64__
 
 
bool
CPUCapabilities::HasMMX()
{
	return fCapabilities >= CAPABILITY_MMX;
}
 
 
bool
CPUCapabilities::HasSSE1()
{
	return fCapabilities >= CAPABILITY_SSE1;
}
 
 
bool
CPUCapabilities::HasSSE2()
{
	return fCapabilities >= CAPABILITY_SSE2;
}
 
 
bool
CPUCapabilities::HasSSE3()
{
	return fCapabilities >= CAPABILITY_SSE3;
}
 
 
bool
CPUCapabilities::HasSSSE3()
{
	return fCapabilities >= CAPABILITY_SSSE3;
}
 
 
bool
CPUCapabilities::HasSSE41()
{
	return fCapabilities >= CAPABILITY_SSE41;
}
 
 
bool
CPUCapabilities::HasSSE42()
{
	return fCapabilities >= CAPABILITY_SSE42;
}
 
 
void
CPUCapabilities::PrintCapabilities()
{
	static const char *CapArray[8] = {
		"", "MMX", "SSE1", "SSE2", "SSE3", "SSSE3", "SSE4.1", "SSE4.2"
	};
 
	printf("CPU is capable of running ");
	if (fCapabilities > 0) {
		for (uint32 i = 1; i <= fCapabilities; i++)
			printf("%s ",CapArray[i]);
	} else {
		printf("no extensions");
	}
	printf("\n");
}

V547 Expression 'maxStandardFunction >= 1' is always true.