🔒 Locked
Finding the full CPU name
Advertisement
Original Post
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
So it's not the CPU speed you want, it's the name of the cpu? :)
Quote:Yes. I'm an idiot. I'll change the thread title [smile]
Original post by Spoonbender
So it's not the CPU speed you want, it's the name of the cpu? :)
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"
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"
Quote:Awesome, thanks. I'll see what Google has to offer.
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"
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}[Edited by - Evil Steve on September 20, 2005 1:59:22 PM]
The simplest way to get at this information is via CPU "brand string". Code snippet:
You also need to do the following:
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.
;// 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.
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 0Also since you first wanted know about speed... this name isnt changed by overclocking, so it could be faster or slower then the string says.
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.
Advertisement