1/*
2 * Copyright (C) 2009 David McPaul
3 *
4 * includes code from sysinfo.c which is
5 * Copyright 2004-2008, Axel D��rfler, axeld@pinc-software.de.
6 * Copyright (c) 2002, Carlos Hasan, for Haiku.
7 *
8 * All rights reserved. Distributed under the terms of the MIT License.
9 */
10
11#include <string.h>
12#include <cpu_type.h>
13
14#include "CpuCapabilities.h"
15
16CPUCapabilities::~CPUCapabilities()
17{
18}
19
20CPUCapabilities::CPUCapabilities()
21{
22	#ifdef __i386__
23		setIntelCapabilities();
24	#endif
25
26	PrintCapabilities();
27}
28
29#ifdef __i386__
30
31void
32CPUCapabilities::setIntelCapabilities()
33{
34	cpuid_info baseInfo;
35	cpuid_info cpuInfo;
36	int32 maxStandardFunction, maxExtendedFunction = 0;
37
38	if (get_cpuid(&baseInfo, 0L, 0L) != B_OK) {
39		// this CPU doesn't support cpuid
40		return;
41	}
42
43	maxStandardFunction = baseInfo.eax_0.max_eax;
44	if (maxStandardFunction >= 500) {
45		maxStandardFunction = 0; /* old Pentium sample chips has cpu signature here */
46	}
47
48	/* Extended cpuid */
49
50	get_cpuid(&cpuInfo, 0x80000000, 0L);
51
52	// extended cpuid is only supported if max_eax is greater than the service id
53	if (cpuInfo.eax_0.max_eax > 0x80000000) {
54		maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
55	}
56
57	if (maxStandardFunction > 0) {
58
59		get_cpuid(&cpuInfo, 1L, 0L);
60		if (cpuInfo.eax_1.features & (1UL << 23)) {
61			capabilities = CAPABILITY_MMX;
62		}
63
64		if (cpuInfo.eax_1.features & (1UL << 25)) {
65			capabilities = CAPABILITY_SSE1;
66		}
67
68		if (cpuInfo.eax_1.features & (1UL << 26)) {
69			capabilities = CAPABILITY_SSE2;
70		}
71
72		if (maxStandardFunction >= 1) {
73			/* Extended features */
74			if (cpuInfo.eax_1.extended_features & (1UL << 0)) {
75				capabilities = CAPABILITY_SSE3;
76			}
77			if (cpuInfo.eax_1.extended_features & (1UL << 9)) {
78				capabilities = CAPABILITY_SSSE3;
79			}
80			if (cpuInfo.eax_1.extended_features & (1UL << 19)) {
81				capabilities = CAPABILITY_SSE41;
82			}
83			if (cpuInfo.eax_1.extended_features & (1UL << 20)) {
84				capabilities = CAPABILITY_SSE42;
85			}
86		}
87	}
88}
89
90#endif
91
92bool
93CPUCapabilities::HasMMX()
94{
95	return capabilities >= CAPABILITY_MMX;
96}
97
98bool
99CPUCapabilities::HasSSE1()
100{
101	return capabilities >= CAPABILITY_SSE1;
102}
103
104bool
105CPUCapabilities::HasSSE2()
106{
107	return capabilities >= CAPABILITY_SSE2;
108}
109
110bool
111CPUCapabilities::HasSSE3()
112{
113	return capabilities >= CAPABILITY_SSE3;
114}
115
116bool
117CPUCapabilities::HasSSSE3()
118{
119	return capabilities >= CAPABILITY_SSSE3;
120}
121
122bool
123CPUCapabilities::HasSSE41()
124{
125	return capabilities >= CAPABILITY_SSE41;
126}
127
128bool
129CPUCapabilities::HasSSE42()
130{
131	return capabilities >= CAPABILITY_SSE42;
132}
133
134void
135CPUCapabilities::PrintCapabilities()
136{
137	static const char *CapArray[8] = {
138		"", "MMX", "SSE1", "SSE2", "SSE3", "SSSE3", "SSE4.1", "SSE4.2"
139	};
140
141	printf("CPU is capable of running ");
142	if (capabilities) {
143		for (uint32 i=1;i<=capabilities;i++) {
144			printf("%s ",CapArray[i]);
145		}
146	} else {
147		printf("no extensions");
148	}
149	printf("\n");
150}
151