Ir para o conteúdo

Detectar o tamanho de linha da cache L1 do processador

program Cache_CPUID;

{$APPTYPE CONSOLE}
uses
  SysUtils;

type
  Registers = record
    _eax_ : cardinal;
    _ebx_ : cardinal;
    _ecx_ : cardinal;
    _edx_ : cardinal;
  end;

procedure CPUID(var regs : Registers);
begin
     asm
       push esi
       push ebx
       push ecx
       push edx
       mov esi, regs
       mov eax, Registers(esi).&_eax_
       mov ebx, Registers(esi).&_ebx_
       mov ecx, Registers(esi).&_ecx_
       mov edx, Registers(esi).&_edx_
       db $0F,$A2   { CPUID }
       mov Registers(esi).&_edx_, edx
       mov Registers(esi).&_ecx_, ecx
       mov Registers(esi).&_ebx_, ebx
       mov Registers(esi).&_eax_, eax
       pop edx
       pop ecx
       pop ebx
       pop esi
     end;
end;

const
     AMDProcessor = 1143;
     IntelProcessor = 1223;
var
     size : cardinal;
     regs : Registers;
     maker : cardinal;
begin
     { Default }
     size := 64;

     { Get the manufacturer code (1223 for Intel, 1143 for AMD) }
     regs._eax_ := 0;
     CPUID(regs);
     maker := regs._ebx_ and $000000FF + regs._ecx_ and $000000FF + regs._edx_ and $000000FF;
     regs._ebx_ := regs._ebx_ shr 8;
     regs._ecx_ := regs._ecx_ shr 8;
     regs._edx_ := regs._edx_ shr 8;
     maker := maker + regs._ebx_ and $000000FF + regs._ecx_ and $000000FF + regs._edx_ and $000000FF;
     regs._ebx_ := regs._ebx_ shr 8;
     regs._ecx_ := regs._ecx_ shr 8;
     regs._edx_ := regs._edx_ shr 8;
     maker := maker + regs._ebx_ and $000000FF + regs._ecx_ and $000000FF + regs._edx_ and $000000FF;
     regs._ebx_ := regs._ebx_ shr 8;
     regs._ecx_ := regs._ecx_ shr 8;
     regs._edx_ := regs._edx_ shr 8;
     maker := maker + regs._ebx_ and $000000FF + regs._ecx_ and $000000FF + regs._edx_ and $000000FF;
     regs._ebx_ := regs._ebx_ shr 8;
     regs._ecx_ := regs._ecx_ shr 8;
     regs._edx_ := regs._edx_ shr 8;

     { For AMD }
     case maker of
       AMDProcessor  : begin
                         writeln('Processador AMD');
                         { Check for support of the extended function $5 }
                         regs._eax_ := $80000000;
                         CPUID(regs);
                         if regs._eax_ >= $80000005 then begin
                           writeln('Usando a funcao 8000 0005');
                           { Call the function }
                           regs._eax_ := $80000005;
                           CPUID(regs);
                           size := regs._ecx_ and $000000FF;
                         end;
                       end;
       IntelProcessor: begin
                         writeln('Processador Intel');
                         { Check for support of the extended function $1D }
                         regs._eax_ := $80000000;
                         CPUID(regs);
                         if regs._eax_ >= $8000001D then begin
                           writeln('Usando a funcao 8000 001D');
                           { Parse through all caches }
                           regs._eax_ := $8000001D;
                           regs._ecx_ := 0;
                           repeat
                             CPUID(regs);
                             { Is this a Level 1 Data/Unified Cache ? }
                             if ((regs._eax_ and $000000FF) = $21) or ((regs._eax_ and $000000FF) = $23) then begin
                               if (regs._ebx_ and $00000FFF) > size then
                                 size := (regs._ebx_ and $00000FFF);
                             end;
                           until (regs._eax_ and $0000000F) = 0;
                         end else begin
                           writeln('Usando a funcao 0000 0001');
                           { Use the standard function 1 }
                           regs._eax_ := 1;
                           CPUID(regs);
                           size := (regs._ebx_ and $0000FF00) shr 5;
                         end;
                       end;
     end;
     writeln('Linha de Cache L1: ',size);
end.