summaryrefslogtreecommitdiff
path: root/dxr3cpu.c
blob: 141495528dfe27d9c9c4ac09796f657c725da74c (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
128
129
130
131
132
133
134
135
136
137
/*
 * 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 vendor: " << 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)
{
  // This works with PIC/non-PIC, from ffmpeg (libavcodec/i386/cputest.c)
  __asm __volatile					\
    ("movl %%ebx, %%esi\n\t"				\
     "cpuid\n\t"						\
     "xchgl %%ebx, %%esi"					\
     : "=a" (out_eax), "=S" (out_ebx),			\
     "=c" (out_ecx), "=d" (out_edx)			\
     : "0" (function));
  return true;
}