Skip to main content
gamedev.net
🔒 Locked

Finding the full CPU name

Started by Evil Steve Sep 20, 2005 at 11:50 AM 9 replies 2.2k views
Original Post
Evil Steve
Evil Steve
Hi all, Does anyone know how to calculate the "real" CPU speed? I know I can use the rdtsc instruction to calculate the CPU speed in MHz, but I'd like to be able to display "AMD Athlon(tm) XP 2600+, ~1.9MHz" instead of "~1.9MHz". The DirectX Diagnostic tool can manage to do this perfectly well, so surely I can too? I know I can get the CPU vendor with the cpuid asm instruction, but I have no idea how to determine that the CPU is E.g. a "XP 2600+". Anyone know? Cheers, Steve
Spoonbender
Spoonbender
So it's not the CPU speed you want, it's the name of the cpu? :)
Evil Steve
Evil Steve
Quote:
Original post by Spoonbender
So it's not the CPU speed you want, it's the name of the cpu? :)
Yes. I'm an idiot. I'll change the thread title [smile]
nife
nife
Both the Intel and AMD docs for detecting the processor type via CPUID also have specifications on the processor types (what something like an AMD Athlon64 is returning in cache, extensions etc.). That way you can identify the processor's name/type.

Don't want to look for the links again (I'd just downloaded it like a year ago when I needed it), but the docs titles are:
"Intel® Processor Identification and the CPUID Instruction"
"AMD Processor Recognition Application Note"
Killers don't end up in jailThey end up on a high-score!
tychon
tychon
Quote:
Original post by Evil Steve
I'd like to be able to display "AMD Athlon(tm) XP 2600+, ~1.9MHz" instead of "~1.9MHz".


I knew I was saving something by not upgrading just yet. Hehe.
Evil Steve
Evil Steve
Quote:
Original post by nife
Both the Intel and AMD docs for detecting the processor type via CPUID also have specifications on the processor types (what something like an AMD Athlon64 is returning in cache, extensions etc.). That way you can identify the processor's name/type.

Don't want to look for the links again (I'd just downloaded it like a year ago when I needed it), but the docs titles are:
"Intel® Processor Identification and the CPUID Instruction"
"AMD Processor Recognition Application Note"
Awesome, thanks. I'll see what Google has to offer.

Edit: Yay, it works for AMD [smile] If anyone cares, here's the code I have:
char szName[49];szName[48] = 0;__asm{   mov eax, 0x80000002      // CPUID 80000002 : processor name string 1   cpuid   mov dword ptr szName, eax   mov dword ptr szName+4, ebx   mov dword ptr szName+8, ecx   mov dword ptr szName+12, edx   mov eax, 0x80000003      // CPUID 80000003 : processor name string 2   cpuid   mov dword ptr szName+16, eax   mov dword ptr szName+20, ebx   mov dword ptr szName+24, ecx   mov dword ptr szName+28, edx   mov eax, 0x80000004      // CPUID 80000004 : processor name string 3   cpuid   mov dword ptr szName+32, eax   mov dword ptr szName+36, ebx   mov dword ptr szName+40, ecx   mov dword ptr szName+44, edx}
In my case, szName now contains "AMD Athlon(tm) XP 2600+". Yay!

[Edited by - Evil Steve on September 20, 2005 1:59:22 PM]
Jan Wassenberg
Jan Wassenberg
The simplest way to get at this information is via CPU "brand string". Code snippet:
;// get CPU brand string (>= Athlon XP, P4)	mov		edi, offset cpu_type	push		-2	pop		esi					;// loop counter: [-2, 0]$1:	lea		eax, [0x80000004+esi]			;// 0x80000002 .. 4	cpuid	stosd	xchg		eax, ebx	stosd	xchg		eax, ecx	stosd	xchg		eax, edx	stosd	inc		esi	jle		$1	;// (already 0 terminated)	mov		[have_brand_string], esi		;// esi = 1 = trueno_brand_str:


You also need to do the following:
	// note: cpu_type is guaranteed to hold 48+1 chars, since that's the	// length of the CPU brand string => we can safely copy short literals.	// (this macro hides us from 'unsafe string code' searches)#define SAFE_STRCPY str##cpy	// fall back to manual detect of CPU type because either:	// - CPU doesn't support brand string (we use a flag to indicate this	//   rather than comparing against a default value because it is safer);	// - the brand string is useless, e.g. "Unknown". this happens on	//   some older boards whose BIOS reprograms the string for CPUs it	//   doesn't recognize.	if(!have_brand_string || strncmp(cpu_type, "Unknow", 6) == 0)	{		if(vendor == AMD)		{			// everything else is either too old, or should have a brand string.			if(family == 6)			{				if(model == 3 || model == 7)					SAFE_STRCPY(cpu_type, "AMD Duron");				else if(model <= 5)					SAFE_STRCPY(cpu_type, "AMD Athlon");				else				{					if(ia32_cap(AMD_MP))						SAFE_STRCPY(cpu_type, "AMD Athlon MP");					else						SAFE_STRCPY(cpu_type, "AMD Athlon XP");				}			}		}		else if(vendor == INTEL)		{			// everything else is either too old, or should have a brand string.			if(family == 6)			{				if(model == 1)					SAFE_STRCPY(cpu_type, "Intel Pentium Pro");				else if(model == 3 || model == 5)					SAFE_STRCPY(cpu_type, "Intel Pentium II");				else if(model == 6)					SAFE_STRCPY(cpu_type, "Intel Celeron");					else					SAFE_STRCPY(cpu_type, "Intel Pentium III");			}		}	}	// cpu_type already holds a valid brand string; pretty it up.	else	{		// strip (tm) from Athlon string		if(!strncmp(cpu_type, "AMD Athlon(tm)", 14))			memmove(cpu_type+10, cpu_type+14, 34);		// remove 2x (R) and CPU freq from P4 string		float freq;		// we can't use this because it isn't necessarily correct - the CPU		// may be overclocked. a variable must be passed, though, since		// scanf returns the number of fields actually stored.		if(sscanf(cpu_type, " Intel(R) Pentium(R) 4 CPU %fGHz", &freq) == 1)			SAFE_STRCPY(cpu_type, "Intel Pentium 4");	}


That's all covered in the CPUID dox, but no need for everyone to rewrite the same basic code. Consider this code licensed under GPL.

// edit: doh, too late. this is still useful, though, because it's much smaller and more complete.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
bakery2k1
bakery2k1
Quote:
Original post by Jan Wassenberg
Consider this code licensed under GPL.


And immediately, your useful code becomes useless for 90% of people.

Tinyn
Tinyn
NVec::NVec(){    #define cpuid(in,a,b,c,d)        asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));    unsigned long In, A, B, C, D, Level;    std::string Temp;    HasMMX      = false;    HasFXSR     = false;    HasSSE      = false;    HasSSE2     = false;    HasSSE3     = false;    Has3DNow    = false;    Has3DNowExt = false;     // In = 0 means ABCD contain the short cpu string    In = 0;    cpuid(In, A, B, C, D);    CpuId = RegsToStr(B, D, C, 0);    Level = A;        // 0x80000002,3,4 are for the segments of the extended string    cpuid(0x80000002, A, B, C, D);    Temp = RegsToStr(A, B, C, D);    ExtendedCpuId += Temp;    cpuid(0x80000003, A, B, C, D);    Temp = RegsToStr(A, B, C, D);    ExtendedCpuId += Temp;    cpuid(0x80000004, A, B, C, D);    Temp = RegsToStr(A, B, C, D);    ExtendedCpuId += Temp;    // 1 is for the chip capabilities    In = 1;    cpuid(In, A, B, C, D);    #ifdef __MMX__        HasMMX      = D & (1<<23);        HasFXSR     = D & (1<<24);    #endif    #ifdef __SSE__        HasSSE      = D & (1<<25);    #endif    #ifdef __SSE2__        HasSSE2     = D & (1<<26);    #endif    #ifdef __SSE3__        HasSSE3     = C & (1<<00);    #endif    // poor 3dnow. No defines for it. And Im not using it yet anyway    Has3DNow    = D & (1<<31);    Has3DNowExt = D & (1<<30);    if(true) {        std::cout << "  CpuId:         " << CpuId << std::endl;        std::cout << "  ExtendedCpuId: " << ExtendedCpuId << std::endl;        std::cout << "  HasMMX         " << HasMMX      << std::endl;        std::cout << "  HasFXSR        " << HasFXSR     << std::endl;        std::cout << "  HasSSE         " << HasSSE      << std::endl;        std::cout << "  HasSSE2        " << HasSSE2     << std::endl;        std::cout << "  HasSSE3        " << HasSSE3     << std::endl;        std::cout << "  Has3DNow       " << Has3DNow    << std::endl;        std::cout << "  Has3DNowExt    " << Has3DNowExt << std::endl;    }}std::string RegsToStr(uint32 A, uint32 B, uint32 C, uint32 D){    char Str[32];    int Loop, Index;    std::string RetStr;    for(Loop=0; Loop < 32; Loop++)        Str[Loop] = '\0';    memcpy(&Str[0], &A, 4);    memcpy(&Str[4], &B, 4);    memcpy(&Str[8], &C, 4);    memcpy(&Str[12], &D, 4);    Str[16] = '\0';    RetStr = Str;    return RetStr;}


The couts at the end fo that ctor print out
  CpuId:         GenuineIntel  ExtendedCpuId:               Intel(R) Pentium(R) 4 CPU 2.00GHz  HasMMX         1  HasFXSR        1  HasSSE         1  HasSSE2        1  HasSSE3        0  Has3DNow       0  Has3DNowExt    0


Also since you first wanted know about speed... this name isnt changed by overclocking, so it could be faster or slower then the string says.
sit
sit
why not query the registry?
HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcesscor\0\ProcessorNameString

this machine calls itself a:
" Intel(R) Pentium(R) 4 CPU 3.40GHz"

[you could have more than one processcor, the cpuid instruction doesn't say anything about that]
rick_appleton
rick_appleton
And yet another small library for getting that kind of info, and more: SysID which is licensed under the ZLIB license. Note that this is still a bit of a (slow) work in progress.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.