如何在Delphi 32中支持SSE2的计算机?
在这里(Windows下)的c + +的方式来做到这一点。
同样的答案,但在Linux下使用GCC。
我理解的相关asm代码摘录如下:
mov eax, 1
cpuid
mov features, edx
在BASM我不太舒服。
我的问题:
我需要将测试包装如下
function IsSSE2: Boolean;
begin
try
Result := False;
//
// Some BASM code here
//
except
Result := False;
end;
end;
请帮帮我。
你也可以在没有汇编器的情况下做到这一点。 只适用于Windows XP和更新版本。
function IsProcessorFeaturePresent(ProcessorFeature: DWORD): BOOL; stdcall;
external kernel32 name 'IsProcessorFeaturePresent';
const
PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10;
function HasSSE2: boolean;
begin
result := IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
end;
我认为这是它:
function SupportsSSE2: LongBool;
const
CPUID_INTEL_SSE2 = $04000000;
asm
push ebx
mov eax, 1
cpuid
mov eax, FALSE
test edx, CPUID_INTEL_SSE2
jz @END
mov eax, TRUE
@END:
pop ebx
end;
以下是graphics32库用于检测处理器功能的代码:
{$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;
你可以调用HasInstructionSet(ciSSE2)
来发现你需要的东西。
上一篇: How to probe a computer if it supports SSE2 in Delphi 32?