From c57f463eded6846abbf905ddcafcbb19267fdea3 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 14 Oct 2012 14:04:27 +0000 Subject: [PATCH] + AVXSupport function to detect if the CPU and OS support AVX git-svn-id: trunk@22641 - --- rtl/i386/cpu.pp | 39 +++++++++++++++++++++++++++++++-------- rtl/x86_64/cpu.pp | 28 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/rtl/i386/cpu.pp b/rtl/i386/cpu.pp index c4775ecd14..c5cc2dc788 100644 --- a/rtl/i386/cpu.pp +++ b/rtl/i386/cpu.pp @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} +{$mode objfpc} unit cpu; interface @@ -25,13 +26,16 @@ unit cpu; { returns the contents of the cr0 register } function cr0 : longint; + function AVXSupport: boolean;inline; + var is_sse3_cpu : boolean = false; implementation {$ASMMODE INTEL} - + var + _AVXSupport : boolean; function cpuid_support : boolean;assembler; { @@ -76,10 +80,19 @@ unit cpu; {$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 _ecx : longint; begin + is_sse3_cpu:=false; if cpuid_support then begin asm @@ -89,13 +102,23 @@ unit cpu; movl %ecx,_ecx popl %ebx end; - sse3_support:=(_ecx and $1)<>0; - end - else - { a cpu with without cpuid instruction supports never sse3 } - sse3_support:=false; + is_sse3_cpu:=(_ecx and $1)<>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); + end; + end; + + + function AVXSupport: boolean;inline; + begin + result:=_AVXSupport; end; begin - is_sse3_cpu:=sse3_support; + SetupSupport; end. diff --git a/rtl/x86_64/cpu.pp b/rtl/x86_64/cpu.pp index 1fd3623ce4..66bdc78bd2 100644 --- a/rtl/x86_64/cpu.pp +++ b/rtl/x86_64/cpu.pp @@ -30,6 +30,7 @@ unit cpu; function InterlockedCompareExchange128Support : boolean;inline; function AESSupport : boolean;inline; + function AVXSupport : boolean;inline; var is_sse3_cpu : boolean = false; @@ -40,6 +41,7 @@ unit cpu; var _AESSupport, + _AVXSupport, _InterlockedCompareExchange128Support : boolean; function InterlockedCompareExchange128Support : boolean;inline; @@ -52,6 +54,10 @@ unit cpu; result:=_AESSupport; end; + function AVXSupport: boolean; + begin + result:=_AVXSupport; + end; function InterlockedCompareExchange128(var Target: Int128Rec; NewValue: Int128Rec; Comperand: Int128Rec): Int128Rec; assembler; { @@ -119,6 +125,19 @@ unit cpu; {$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; var _ecx : longint; @@ -132,6 +151,15 @@ unit cpu; end; _InterlockedCompareExchange128Support:=(_ecx and $2000)<>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; end;