From 1f6d86991f191568d45484f2b3740c2dcd0a7b45 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 3 Oct 2012 16:46:17 +0200 Subject: [PATCH] x86: Add YASM implementations of cpuid and xgetbv from x264 This allows detecting CPU features with builds that have neither gcc inline assembly nor the right compiler intrinsics enabled. --- libavutil/x86/Makefile | 3 +- libavutil/x86/cpu.c | 17 +++++++- libavutil/x86/cpu.h | 4 ++ libavutil/x86/cpuid.asm | 91 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 libavutil/x86/cpuid.asm diff --git a/libavutil/x86/Makefile b/libavutil/x86/Makefile index 4546353669..3dd696c26a 100644 --- a/libavutil/x86/Makefile +++ b/libavutil/x86/Makefile @@ -1,4 +1,5 @@ OBJS += x86/cpu.o \ x86/float_dsp_init.o \ -YASM-OBJS += x86/float_dsp.o \ +YASM-OBJS += x86/cpuid.o \ + x86/float_dsp.o \ diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 5de60147c6..fb1dd299bc 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -22,10 +22,21 @@ #include #include + #include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" #include "libavutil/cpu.h" -#if HAVE_INLINE_ASM +#if HAVE_YASM + +#define cpuid(index, eax, ebx, ecx, edx) \ + ff_cpu_cpuid(index, &eax, &ebx, &ecx, &edx) + +#define xgetbv(index, eax, edx) \ + ff_cpu_xgetbv(index, &eax, &edx) + +#elif HAVE_INLINE_ASM + /* ebx saving is necessary for PIC. gcc seems unable to see it alone */ #define cpuid(index, eax, ebx, ecx, edx) \ __asm__ volatile ( \ @@ -90,6 +101,10 @@ #define cpuid_test() 1 +#elif HAVE_YASM + +#define cpuid_test ff_cpu_cpuid_test + #elif HAVE_INLINE_ASM || HAVE_RWEFLAGS static int cpuid_test(void) diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index e14cb57416..e4f6f0bd5a 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -54,4 +54,8 @@ #define INLINE_AVX(flags) CPUEXT(flags, _INLINE, AVX) #define INLINE_FMA4(flags) CPUEXT(flags, _INLINE, FMA4) +void ff_cpu_cpuid(int index, int *eax, int *ebx, int *ecx, int *edx); +void ff_cpu_xgetbv(int op, int *eax, int *edx); +int ff_cpu_cpuid_test(void); + #endif /* AVUTIL_X86_CPU_H */ diff --git a/libavutil/x86/cpuid.asm b/libavutil/x86/cpuid.asm new file mode 100644 index 0000000000..d2ac1f01dc --- /dev/null +++ b/libavutil/x86/cpuid.asm @@ -0,0 +1,91 @@ +;***************************************************************************** +;* Copyright (C) 2005-2010 x264 project +;* +;* Authors: Loren Merritt +;* Jason Garrett-Glaser +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "x86inc.asm" + +SECTION .text + +;----------------------------------------------------------------------------- +; void ff_cpu_cpuid(int index, int *eax, int *ebx, int *ecx, int *edx) +;----------------------------------------------------------------------------- +cglobal cpu_cpuid, 5,7 + push rbx + push r4 + push r3 + push r2 + push r1 + mov eax, r0d + xor ecx, ecx + cpuid + pop r4 + mov [r4], eax + pop r4 + mov [r4], ebx + pop r4 + mov [r4], ecx + pop r4 + mov [r4], edx + pop rbx + RET + +;----------------------------------------------------------------------------- +; void ff_cpu_xgetbv(int op, int *eax, int *edx) +;----------------------------------------------------------------------------- +cglobal cpu_xgetbv, 3,7 + push r2 + push r1 + mov ecx, r0d + xgetbv + pop r4 + mov [r4], eax + pop r4 + mov [r4], edx + RET + +%if ARCH_X86_64 == 0 +;----------------------------------------------------------------------------- +; int ff_cpu_cpuid_test(void) +; return 0 if unsupported +;----------------------------------------------------------------------------- +cglobal cpu_cpuid_test + pushfd + push ebx + push ebp + push esi + push edi + pushfd + pop eax + mov ebx, eax + xor eax, 0x200000 + push eax + popfd + pushfd + pop eax + xor eax, ebx + pop edi + pop esi + pop ebp + pop ebx + popfd + ret +%endif