[fpc-devel] AMD & Intel CPUCount (was: Feature announcement: Extension of TThread's interface)

Ewald ewald at yellowcouch.org
Thu Dec 27 23:06:41 CET 2012


Right, since the /proc/cpuinfo (a) is not available on many platforms
and (b) has no standard output format, I decided to fix the half done
CPUID approach. Here it goes (note: don't shoot me if my assembly is a
bit weird, I've only learned part of it by experimenting):
    [see below]

For time being there are only two CPU kinds supported (GenuineIntel and
AuthenticAMD), in other cases it returns the # of logical CPU's. Feel
free to extend the code with other CPU ID's ;-)

Oh, and the important part: The function has been tested on a Core 2 Duo
and an Intel i7, and works correctly. If someone would be so kind to
test it on some other CPU's that would be great! [I'm not 100% of the
hexadecimal of `AuthenticAMD` you see]


program cpucount;

{$mode objfpc}
{$asmmode att}

Function GetCores: LongWord;
Begin
    Asm
        //Vendor ID
        MOV $0, %eax
        MOV $0, %ecx
        CPUID
       
        // ?= GenuineIntel
        CMP $0x756e6547, %ebx
        JNE .LnotGenuineIntel
        CMP $0x49656e69, %edx
        JNE .LnotGenuineIntel
        CMP $0x6c65746e, %ecx
        JNE .LnotGenuineIntel
       
        MOV $4, %eax
        MOV $0, %ecx
        CPUID
       
        SHR $26, %eax
        AND $0x3F, %eax
        ADD $1, %eax
        MOV %eax, __RESULT
        JMP .LReturn
       
        .LnotGenuineIntel:
       
        // ?= AuthenticAMD
        CMP $0x68747541, %ebx
        JNE .LnotAuthenticAMD
        CMP $0x69746e65, %edx
        JNE .LnotAuthenticAMD
        CMP $0x444d4163, %ecx
        JNE .LnotAuthenticAMD
       
        MOV $0x80000008, %eax
        MOV $0, %ecx
        CPUID
       
        AND $0xFF, %ecx
        ADD $1, %ecx
        MOV %ecx, __RESULT
        JMP .LReturn
       
        .LnotAuthenticAMD:
       
        //Return #logical CPU's
        MOV $1, %eax
        MOV $0, %ecx
        CPUID
       
        SHR $16, %ebx
        AND $0xFF, %ebx
        MOV %ebx, __RESULT
       
        .LReturn:
    End ['eax', 'ebx', 'ecx', 'edx'];
End;

Begin
    Writeln('#CPU cores: ', GetCores);
End.



-- 
Ewald




More information about the fpc-devel mailing list