+ AVXSupport function to detect if the CPU and OS support AVX

git-svn-id: trunk@22641 -
This commit is contained in:
florian 2012-10-14 14:04:27 +00:00
parent 91f1a8736c
commit c57f463ede
2 changed files with 59 additions and 8 deletions

View File

@ -13,6 +13,7 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************} **********************************************************************}
{$mode objfpc}
unit cpu; unit cpu;
interface interface
@ -25,13 +26,16 @@ unit cpu;
{ returns the contents of the cr0 register } { returns the contents of the cr0 register }
function cr0 : longint; function cr0 : longint;
function AVXSupport: boolean;inline;
var var
is_sse3_cpu : boolean = false; is_sse3_cpu : boolean = false;
implementation implementation
{$ASMMODE INTEL} {$ASMMODE INTEL}
var
_AVXSupport : boolean;
function cpuid_support : boolean;assembler; function cpuid_support : boolean;assembler;
{ {
@ -76,10 +80,19 @@ unit cpu;
{$ASMMODE ATT} {$ASMMODE ATT}
function sse3_support : boolean; function XGETBV(i : dword) : int64;assembler;
asm
movl %eax,%ecx
// older FPCs don't know the xgetbv opcode
.byte 0x0f,0x01,0xd0
end;
procedure SetupSupport;
var var
_ecx : longint; _ecx : longint;
begin begin
is_sse3_cpu:=false;
if cpuid_support then if cpuid_support then
begin begin
asm asm
@ -89,13 +102,23 @@ unit cpu;
movl %ecx,_ecx movl %ecx,_ecx
popl %ebx popl %ebx
end; end;
sse3_support:=(_ecx and $1)<>0; is_sse3_cpu:=(_ecx and $1)<>0;
end _AVXSupport:=
else { XGETBV suspport? }
{ a cpu with without cpuid instruction supports never sse3 } ((_ecx and $08000000)<>0) and
sse3_support:=false; { xmm and ymm state enabled? }
((XGETBV(0) and %110)=%110) and
{ avx supported? }
((_ecx and $10000000)<>0);
end;
end;
function AVXSupport: boolean;inline;
begin
result:=_AVXSupport;
end; end;
begin begin
is_sse3_cpu:=sse3_support; SetupSupport;
end. end.

View File

@ -30,6 +30,7 @@ unit cpu;
function InterlockedCompareExchange128Support : boolean;inline; function InterlockedCompareExchange128Support : boolean;inline;
function AESSupport : boolean;inline; function AESSupport : boolean;inline;
function AVXSupport : boolean;inline;
var var
is_sse3_cpu : boolean = false; is_sse3_cpu : boolean = false;
@ -40,6 +41,7 @@ unit cpu;
var var
_AESSupport, _AESSupport,
_AVXSupport,
_InterlockedCompareExchange128Support : boolean; _InterlockedCompareExchange128Support : boolean;
function InterlockedCompareExchange128Support : boolean;inline; function InterlockedCompareExchange128Support : boolean;inline;
@ -52,6 +54,10 @@ unit cpu;
result:=_AESSupport; result:=_AESSupport;
end; end;
function AVXSupport: boolean;
begin
result:=_AVXSupport;
end;
function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler; function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler;
{ {
@ -119,6 +125,19 @@ unit cpu;
{$endif win64} {$endif win64}
function XGETBV(i : dword) : int64;assembler;
asm
{$ifndef win64}
movq %rdi,%rcx
{$endif win64}
// older FPCs don't know the xgetbv opcode
.byte 0x0f,0x01,0xd0
andl $0xffffffff,%eax
shll $32,%rdx
orq %rdx,%rax
end;
procedure SetupSupport; procedure SetupSupport;
var var
_ecx : longint; _ecx : longint;
@ -132,6 +151,15 @@ unit cpu;
end; end;
_InterlockedCompareExchange128Support:=(_ecx and $2000)<>0; _InterlockedCompareExchange128Support:=(_ecx and $2000)<>0;
_AESSupport:=(_ecx and $2000000)<>0; _AESSupport:=(_ecx and $2000000)<>0;
_AVXSupport:=
{ XGETBV suspport? }
((_ecx and $08000000)<>0) and
{ xmm and ymm state enabled? }
((XGETBV(0) and %110)=%110) and
{ avx supported? }
((_ecx and $10000000)<>0);
is_sse3_cpu:=(_ecx and $1)<>0; is_sse3_cpu:=(_ecx and $1)<>0;
end; end;