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
128
129
130
|
/*
* 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);
}
}
}
}
// MPlayer, Xine-lib, Transcode: SSE implies MMXEXT
m_Info.MMXEXT = m_Info.MMXEXT || m_Info.SSE;
// 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;
}
|