summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOneric <oneric@oneric.stub>2022-03-15 23:00:05 +0100
committerOneric <oneric@oneric.stub>2022-03-27 22:28:59 +0200
commit725da4729b99c98ee94ffe49a253650450a64f4d (patch)
treeda00de4821a99ca1ab0c8ccbf902ff3c91f54dac
parent9608c8c838e1046601c27f6473e23654fedf1716 (diff)
downloadlibass-725da4729b99c98ee94ffe49a253650450a64f4d.tar.bz2
libass-725da4729b99c98ee94ffe49a253650450a64f4d.tar.xz
asm/x86: check if cpuid is available before usage
The cpuid instruction was only introduced after i486, meaning there are ix86 CPUs on which our default configuration will build but crash during runtime when cpuid is executed. To avoid this, check for the instructions availability by testing if bit 21 of EFLAGS is writable as documented by AMD, Cyrix, Intel and NexGen. AMD, p.165: https://www.amd.com/system/files/TechDocs/24594.pdf Cyrix, p.10: https://www.ardent-tool.com/CPU/docs/Cyrix/MII/94329_2.pdf Intel, ch.3 p.190: https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf NexGen: https://www.ardent-tool.com/CPU/docs/NexGen/cpuid.pdf
-rw-r--r--libass/ass_utils.c3
-rw-r--r--libass/x86/cpuid.asm24
-rw-r--r--libass/x86/cpuid.h1
3 files changed, 28 insertions, 0 deletions
diff --git a/libass/ass_utils.c b/libass/ass_utils.c
index 0acc891..a9db9be 100644
--- a/libass/ass_utils.c
+++ b/libass/ass_utils.c
@@ -40,6 +40,9 @@ void ass_cpu_capabilities(bool *sse2, bool *avx2)
*sse2 = false;
*avx2 = false;
+ if (!ass_has_cpuid())
+ return;
+
uint32_t eax = 0, ebx, ecx, edx;
ass_get_cpuid(&eax, &ebx, &ecx, &edx);
uint32_t max_leaf = eax;
diff --git a/libass/x86/cpuid.asm b/libass/x86/cpuid.asm
index 09b3e77..b27d906 100644
--- a/libass/x86/cpuid.asm
+++ b/libass/x86/cpuid.asm
@@ -23,6 +23,30 @@
SECTION .text
;------------------------------------------------------------------------------
+; uint32_t has_cpuid( void );
+;------------------------------------------------------------------------------
+
+INIT_XMM
+cglobal has_cpuid, 0, 0, 0
+%if ARCH_X86_64
+ mov eax, 1
+%else
+ pushfd
+ pop ecx
+ mov eax, ecx
+ xor eax, 0x00200000
+ push eax
+ popfd
+ pushfd
+ pop eax
+ xor eax, ecx
+ and eax, 0x00200000 ; non-zero if bit is writable
+ push ecx ; Restore original EFLAGS
+ popfd
+%endif
+ RET
+
+;------------------------------------------------------------------------------
; void get_cpuid( uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
;------------------------------------------------------------------------------
diff --git a/libass/x86/cpuid.h b/libass/x86/cpuid.h
index ab50292..0218cde 100644
--- a/libass/x86/cpuid.h
+++ b/libass/x86/cpuid.h
@@ -21,6 +21,7 @@
#include <stdint.h>
+uint32_t ass_has_cpuid( void );
void ass_get_cpuid( uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
void ass_get_xgetbv( uint32_t op, uint32_t *eax, uint32_t *edx );