Este es el código utilizado por la biblioteca graphics32 para detectar las características del procesador:
{$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;
Puede llamar HasInstructionSet(ciSSE2)
para descubrir lo que necesita.
Tenga cuidado. Tanto la CPU como el sistema operativo deben ser compatibles con SSE2. El sistema operativo debe admitirlo porque los registros SSE se guardan en la memoria en un cambio de contexto, y el sistema operativo tiene que suministrar el área de memoria. Es por eso que a veces no es suficiente para probar el bit de función de la CPU SSE2. Es también por eso que ve pruebas para XSTORE y soporte FXSAVE. IIRC, están habilitados si el sistema operativo proporciona el área de memoria; de lo contrario, el sistema operativo lo desactiva (algunos renuncian a mano). Por lo general, hoy no es un problema, a menos que admita procesadores y sistemas operativos más antiguos. Consulte también * Sección 11.6.2, Comprobación del soporte de SSE/SSE2 * en el Manual de programadores de Intel. – jww
Consulte también [¿Determinación del soporte del procesador para SSE2?] (Https://stackoverflow.com/q/2403660/608639) y [Cómo verificar si una CPU admite el conjunto de instrucciones SSE3?] (Https://stackoverflow.com/ q/6121792/608639). La segunda pregunta proporciona detalles del soporte del sistema operativo. – jww