Ecco il codice usato dalla libreria graphics32 di rilevare le caratteristiche del processore:
{$IFDEF WIN64}
{$DEFINE TARGET_x64}
{$ENDIF}
type
TCPUInstructionSet = (ciMMX, ciEMMX, ciSSE, ciSSE2, ci3DNow, ci3DNowExt);
const
CPUISChecks: Array[TCPUInstructionSet] of Cardinal =
($800000, $400000, $2000000, $4000000, $80000000, $40000000);
{ciMMX , ciEMMX, ciSSE , ciSSE2 , ci3DNow , ci3DNowExt}
function CPUID_Available: Boolean;
asm
{$IFDEF TARGET_x64}
MOV EDX,False
PUSHFQ
POP RAX
MOV ECX,EAX
XOR EAX,$00200000
PUSH RAX
POPFQ
PUSHFQ
POP RAX
XOR ECX,EAX
JZ @1
MOV EDX,True
@1: PUSH RAX
POPFQ
MOV EAX,EDX
{$ELSE}
MOV EDX,False
PUSHFD
POP EAX
MOV ECX,EAX
XOR EAX,$00200000
PUSH EAX
POPFD
PUSHFD
POP EAX
XOR ECX,EAX
JZ @1
MOV EDX,True
@1: PUSH EAX
POPFD
MOV EAX,EDX
{$ENDIF}
end;
function CPU_Signature: Integer;
asm
{$IFDEF TARGET_x64}
PUSH RBX
MOV EAX,1
CPUID
POP RBX
{$ELSE}
PUSH EBX
MOV EAX,1
{$IFDEF FPC}
CPUID
{$ELSE}
DW $A20F // CPUID
{$ENDIF}
POP EBX
{$ENDIF}
end;
function CPU_Features: Integer;
asm
{$IFDEF TARGET_x64}
PUSH RBX
MOV EAX,1
CPUID
POP RBX
MOV EAX,EDX
{$ELSE}
PUSH EBX
MOV EAX,1
{$IFDEF FPC}
CPUID
{$ELSE}
DW $A20F // CPUID
{$ENDIF}
POP EBX
MOV EAX,EDX
{$ENDIF}
end;
function CPU_ExtensionsAvailable: Boolean;
asm
{$IFDEF TARGET_x64}
PUSH RBX
MOV @Result, True
MOV EAX, $80000000
CPUID
CMP EAX, $80000000
JBE @NOEXTENSION
JMP @EXIT
@NOEXTENSION:
MOV @Result, False
@EXIT:
POP RBX
{$ELSE}
PUSH EBX
MOV @Result, True
MOV EAX, $80000000
{$IFDEF FPC}
CPUID
{$ELSE}
DW $A20F // CPUID
{$ENDIF}
CMP EAX, $80000000
JBE @NOEXTENSION
JMP @EXIT
@NOEXTENSION:
MOV @Result, False
@EXIT:
POP EBX
{$ENDIF}
end;
function CPU_ExtFeatures: Integer;
asm
{$IFDEF TARGET_x64}
PUSH RBX
MOV EAX, $80000001
CPUID
POP RBX
MOV EAX,EDX
{$ELSE}
PUSH EBX
MOV EAX, $80000001
{$IFDEF FPC}
CPUID
{$ELSE}
DW $A20F // CPUID
{$ENDIF}
POP EBX
MOV EAX,EDX
{$ENDIF}
end;
function HasInstructionSet(const InstructionSet: TCPUInstructionSet): Boolean;
// Must be implemented for each target CPU on which specific functions rely
begin
Result := False;
if not CPUID_Available then Exit; // no CPUID available
if CPU_Signature shr 8 and $0F < 5 then Exit; // not a Pentium class
case InstructionSet of
ci3DNow, ci3DNowExt:
{$IFNDEF FPC}
if not CPU_ExtensionsAvailable or (CPU_ExtFeatures and CPUISChecks[InstructionSet] = 0) then
{$ENDIF}
Exit;
ciEMMX:
begin
// check for SSE, necessary for Intel CPUs because they don't implement the
// extended info
if (CPU_Features and CPUISChecks[ciSSE] = 0) and
(not CPU_ExtensionsAvailable or (CPU_ExtFeatures and CPUISChecks[ciEMMX] = 0)) then
Exit;
end;
else
if CPU_Features and CPUISChecks[InstructionSet] = 0 then
Exit; // return -> instruction set not supported
end;
Result := True;
end;
È possibile chiamare HasInstructionSet(ciSSE2)
per scoprire che cosa avete bisogno.
Fare attenzione. Sia la CPU che il sistema operativo devono supportare SSE2. Il sistema operativo deve supportarlo perché i registri SSE vengono salvati in memoria su un interruttore di contesto e il sistema operativo deve fornire l'area della memoria. Ecco perché a volte non è sufficiente testare il bit della cpu della SSE2. Questo è anche il motivo per cui vedi i test per il supporto XSTORE e FXSAVE. IIRC, sono abilitati se il sistema operativo fornisce l'area di memoria; altrimenti il sistema operativo lo disabilita (rinuncia a qualche mano). Di solito non è un problema al giorno d'oggi, a meno che non supporti processori e sistemi operativi meno recenti. Vedi anche Sezione 11.6.2, Verifica del supporto SSE/SSE2 * nel Manuale dei programmatori Intel. – jww
Vedere anche [Determinare il supporto del processore per SSE2?] (Https://stackoverflow.com/q/2403660/608639) e [Come verificare se una CPU supporta il set di istruzioni SSE3?] (Https://stackoverflow.com/ q/6121792/608 mila seicentotrentanove). La seconda domanda fornisce dettagli sul supporto del sistema operativo. – jww