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"
// ==================================
//! constructor
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;
}
|