summaryrefslogtreecommitdiff
path: root/dxr3cpu.c
blob: 4666e8917c993f385059b21b9351eb50b5932b85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* dxr3cpu.c
*
* Copyright (C) 2004 Christian Gmeiner
*
* Taken from Nesseia-Renderengine Copyright (C) 2003-2004 Christian Gmeiner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*/

#include "dxr3cpu.h"
#include "dxr3log.h"
#include "dxr3memcpy.h"

// ==================================
// const.
cDxr3CPU::cDxr3CPU()
{
	unsigned long eax,ebx,edx,unused;
	
	// readout the vendor
	cpuid(0,eax,ebx,unused,edx);
	
	// set Vendor to ""
	memset(m_Info.Vendor, 0, 16);
	
	// connect the single register values to the vendor string
	// maybe there is an better solution - i will google :)
	*(unsigned long *)(m_Info.Vendor) = ebx;
	*(unsigned long *)(m_Info.Vendor + 4) = edx;
	*(unsigned long *)(m_Info.Vendor + 8) = unused;
	
	// check the features
	// could we get the needed infos?
	if (cpuid(1,eax,ebx,unused,edx))
	{
		m_Info.MMX = ((edx & 1<<23) != 0);
		m_Info.SSE = ((edx & 1<<25) != 0);
		m_Info.SSE2= ((edx & 1<<26) != 0);
		m_Info.RDTSC=((edx & 1<<4) != 0); /*0x10*/
		m_Info.HT  = ((edx & 1<<28) !=0);		// should we do here addinonal checks?
		
		// 3DNow is a litle bit harder to read out
		// We read the ext. CPUID level 0x80000000
		if (cpuid(0x80000000,eax,ebx,unused,edx))
		{
			// now in eax there is the max. supported extended CPUID level
			// we check if theres an extended CPUID level support
			if (eax >= 0x80000001)
			{
				// If we can access the extended CPUID level 0x80000001 we get the
				// edx register
				if (cpuid(0x80000001,eax,ebx,unused,edx))
				{
					// Now we can mask some AMD specific cpu extensions
					// 22 ... Extended MMX_MultimediaExtensions
					m_Info.MMXEXT = ((edx & 1<<22) != 0);
					m_Info.AMD64Bit = ((edx & 1<<29) != 0);
					// 30 ... Extended 3DNOW_InstructionExtensions
					m_Info.Now = ((edx & (1<<31)) != 0);
				}
			}
		}
	}

	// fill cabs
	if (m_Info.MMX)
	{
		m_Info.caps = CC_MMX;
	}

	if (m_Info.MMXEXT)
	{
		m_Info.caps |= CC_MMXEXT;
	}

	if (m_Info.SSE)
	{
		m_Info.caps |= CC_SSE;
	}

	if (m_Info.Now)
	{
		m_Info.caps |= CC_3DNOW;
	}

	// print some infos about cpu
	cLog::Instance() << "cpu vandor: " << m_Info.Vendor << "\n";
	cLog::Instance() << "cpu extensions:\n";
	cLog::Instance() << "mmx:      " << m_Info.MMX << "\n";
	cLog::Instance() << "mmx-ext:  " << m_Info.MMXEXT << "\n";
	cLog::Instance() << "sse:      " << m_Info.SSE << "\n";
	cLog::Instance() << "sse2:     " << m_Info.SSE2 << "\n";
	cLog::Instance() << "3dnow:    " << m_Info.Now << "\n";

	// now we select the best memcpy mehtode
	cDxr3MemcpyBench Benchmark(m_Info.caps);
}

// ==================================
// does the cpu support cpuid instructions
bool cDxr3CPU::CheckCPUIDPresence()
{
	// todo
	return true;
}

// ==================================
// cpuid function
bool cDxr3CPU::cpuid(unsigned long function, unsigned long& out_eax, unsigned long& out_ebx, unsigned long& out_ecx, unsigned long& out_edx)
{
	asm("cpuid": "=a" (out_eax), "=b" (out_ebx), "=c" (out_ecx), "=d" (out_edx) : "a" (function));
	return true;
}